diff --git a/.gitignore b/.gitignore index 5916bfe..e8d6686 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ .vscode test .gitignore -.travis.yml \ No newline at end of file +.travis.yml +lib \ No newline at end of file diff --git a/README.MD b/README.MD index 5ab410b..cc3bb66 100644 --- a/README.MD +++ b/README.MD @@ -1,7 +1,6 @@ TTGO-T-Beam ===================== - ![](image/product.jpg) @@ -12,7 +11,9 @@ TTGO-T-Beam | LORA_MISO | 19 | 19 | | LORA_MOSI | 27 | 27 | | LORA_SS | 18 | 18 | -| LORA_DI0 | 26 | 26 | +| LORA_DIO0 | 26 | 26 | +| LORA_DIO1 | 33 | 33 | +| LORA_DIO2 | 32 | 32 | | LORA_RST | 23 | 23 | | GPS_RX_PIN | 34 | 12 | | GPS_TX_PIN | 12 | 15 | @@ -37,7 +38,7 @@ TTGO-T-Beam ## Button Function: -- Click button 2 will cycle the motherboard function, the default start to enable GPS positioning, the second click will be set to lora send, the third click will be set to lora receive, long press for two seconds and then release, will enter deep sleep +- Click button 2 will cycle the user function, the default start to enable GPS positioning, the second click will be set to lora send, the third click will be set to lora receive, long press for two seconds and then release, will enter deep sleep ## About OLED: - The boot will scan the I2C device. If the OLED is found, all log information will be displayed in the OLED. If not, it will be printed on the serial port. diff --git a/image/deepsleep.jpg b/image/deepsleep.jpg new file mode 100644 index 0000000..9859d99 Binary files /dev/null and b/image/deepsleep.jpg differ diff --git a/image/product.jpg b/image/product.jpg new file mode 100644 index 0000000..844c77b Binary files /dev/null and b/image/product.jpg differ diff --git a/platformio.ini b/platformio.ini index b08149b..f214314 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,10 +13,8 @@ platform = espressif32 board = esp32dev framework = arduino -upload_port = COM11 -monitor_port = COM11 -; upload_port = COM8 -; monitor_port = COM8 +upload_port = COM26 +monitor_port = COM26 monitor_speed = 115200 upload_speed = 2000000 @@ -26,7 +24,7 @@ lib_deps = AXP202X_Library ;https://github.com/lewisxhe/AXP202X_Library TinyGPSPlus ;https://github.com/mikalhart/TinyGPSPlus ESP8266_SSD1306 ;https://github.com/ThingPulse/esp8266-oled-ssd1306 - LoRa ;https://github.com/dragino/Lora + RadioLib ;https://github.com/jgromes/RadioLib diff --git a/T-SX1262.pdf b/schematic/T-SX1262.pdf similarity index 100% rename from T-SX1262.pdf rename to schematic/T-SX1262.pdf diff --git a/schematic/T_BeamV1.0.pdf b/schematic/T_BeamV1.0.pdf new file mode 100644 index 0000000..6e87b33 Binary files /dev/null and b/schematic/T_BeamV1.0.pdf differ diff --git a/src/LilyGO-T-Beam.ino b/src/LilyGO-T-Beam.ino index ada795a..d80210d 100644 --- a/src/LilyGO-T-Beam.ino +++ b/src/LilyGO-T-Beam.ino @@ -1,456 +1,549 @@ -#include "board_def.h" -#include -#include -#include "axp20x.h" -#include -#include - -#ifndef AXP192_SLAVE_ADDRESS -#define AXP192_SLAVE_ADDRESS 0x34 -#endif - -SSD1306_OBJECT(); -UBLOX_GPS_OBJECT(); - -AXP20X_Class axp; -uint8_t program = 0; -bool ssd1306_found = false; -bool axp192_found = false; -bool loraBeginOK = false; - -uint64_t dispMap = 0; -String dispInfo; -char buff[5][256]; - -uint64_t gpsSec = 0; -bool pmu_irq = false; -#define BUTTONS_MAP {BUTTON_PIN} - -Button2 *pBtns = nullptr; -uint8_t g_btns[] = BUTTONS_MAP; -#define ARRARY_SIZE(a) (sizeof(a) / sizeof(a[0])) - -Ticker btnTick; - -String baChStatus = "No charging"; -String recv = ""; - -/************************************ - * BUTTON - * *********************************/ -void button_callback(Button2 &b) -{ - for (int i = 0; i < ARRARY_SIZE(g_btns); ++i) { - if (pBtns[i] == b) { - if (ssd1306_found) { - ui.nextFrame(); - } - program = program + 1 > 2 ? 0 : program + 1; - } - } -} - -void button_loop() -{ - for (int i = 0; i < ARRARY_SIZE(g_btns); ++i) { - pBtns[i].loop(); - } -} - -void button_init() -{ - uint8_t args = ARRARY_SIZE(g_btns); - pBtns = new Button2 [args]; - for (int i = 0; i < args; ++i) { - pBtns[i] = Button2(g_btns[i]); - pBtns[i].setPressedHandler(button_callback); - } - pBtns[0].setLongClickHandler([](Button2 & b) { - if (ssd1306_found) { - oled.displayOff(); - } - Serial.println("Go to Sleep"); - if (axp192_found) { - axp.setChgLEDMode(AXP20X_LED_OFF); - axp.setPowerOutPut(AXP192_LDO2, AXP202_OFF); - axp.setPowerOutPut(AXP192_LDO3, AXP202_OFF); - axp.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); - // axp.setPowerOutPut(AXP192_DCDC3, AXP202_OFF); - axp.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); - axp.setPowerOutPut(AXP192_EXTEN, AXP202_OFF); - } - - delay(20); - esp_sleep_enable_ext1_wakeup(BUTTON_PIN_MASK, ESP_EXT1_WAKEUP_ALL_LOW); - esp_deep_sleep_start(); - }); -} - -void msOverlay(OLEDDisplay *display, OLEDDisplayUiState *state) -{ - static char volbuffer[128]; - display->setTextAlignment(TEXT_ALIGN_LEFT); - display->setFont(ArialMT_Plain_10); - - display->drawString(0, 0, baChStatus); - - if (axp.isBatteryConnect()) { - snprintf(volbuffer, sizeof(volbuffer), "%.2fV/%.2fmA", axp.getBattVoltage() / 1000.0, axp.isChargeing() ? axp.getBattChargeCurrent() : axp.getBattDischargeCurrent()); - display->drawString(62, 0, volbuffer); - } else { - multi_heap_info_t info; - heap_caps_get_info(&info, MALLOC_CAP_INTERNAL); - snprintf(volbuffer, sizeof(volbuffer), "%u/%uKB", info.total_allocated_bytes / 1024, info.total_free_bytes / 1024); - display->drawString(75, 0, volbuffer); - } -} - -void drawFrame1(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -{ - - display->setFont(ArialMT_Plain_10); - display->setTextAlignment(TEXT_ALIGN_CENTER); - - if (!gps.location.isValid()) { - display->drawString(64 + x, 11 + y, buff[0]); - display->drawString(64 + x, 22 + y, buff[1]); - } else { - display->drawString(64 + x, 11 + y, buff[0]); - display->drawString(64 + x, 22 + y, buff[1]); - display->drawString(64 + x, 33 + y, buff[2]); - display->drawString(64 + x, 44 + y, buff[3]); - } -} - -void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -{ - display->setFont(ArialMT_Plain_10); - display->setTextAlignment(TEXT_ALIGN_CENTER); - display->drawString(64 + x, 11 + y, buff[0]); - display->drawString(64 + x, 22 + y, buff[1]); -} - -void drawFrame3(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -{ - display->setFont(ArialMT_Plain_10); - display->setTextAlignment(TEXT_ALIGN_CENTER); - display->drawString(64 + x, 9 + y, buff[0]); - display->drawString(64 + x, 22 + y, recv == "" ? "No message" : recv); - display->drawString(64 + x, 35 + y, buff[1]); -} - -//PMU -void drawFrame4(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -{ - display->setFont(ArialMT_Plain_10); - display->setTextAlignment(TEXT_ALIGN_CENTER); - if (!axp192_found) { - display->drawString(64 + x, 22 + y, "PMU Begin FAIL"); - return; - } - //TODO:: - display->drawString(64 + x, 22 + y, "Empty"); -} - - -FrameCallback frames[] = {drawFrame1, drawFrame2, drawFrame3, /*drawFrame4*/}; -OverlayCallback overlays[] = { msOverlay }; - -void ssd1306_init() -{ -#ifdef ENABLE_SSD1306 - if (!ssd1306_found) { - Serial.println("SSD1306 not found"); - return; - } - if (oled.init()) { - oled.flipScreenVertically(); - oled.setFont(ArialMT_Plain_16); - oled.setTextAlignment(TEXT_ALIGN_CENTER); - } else { - Serial.println("SSD1306 Begin FAIL"); - } - Serial.println("SSD1306 Begin PASS"); - ui.setTargetFPS(30); - ui.disableAutoTransition(); - ui.setIndicatorPosition(BOTTOM); - ui.setIndicatorDirection(LEFT_RIGHT); - ui.setFrameAnimation(SLIDE_LEFT); - ui.setFrames(frames, ARRARY_SIZE(frames)); - if (axp192_found) { - ui.setOverlays(overlays, ARRARY_SIZE(overlays)); - } -#endif -} - - - -void scanI2Cdevice(void) -{ - byte err, addr; - int nDevices = 0; - for (addr = 1; addr < 127; addr++) { - Wire.beginTransmission(addr); - err = Wire.endTransmission(); - if (err == 0) { - Serial.print("I2C device found at address 0x"); - if (addr < 16) - Serial.print("0"); - Serial.print(addr, HEX); - Serial.println(" !"); - nDevices++; - - if (addr == SSD1306_ADDRESS) { - ssd1306_found = true; - Serial.println("ssd1306 display found"); - } - if (addr == AXP192_SLAVE_ADDRESS) { - axp192_found = true; - Serial.println("axp192 PMU found"); - } - } else if (err == 4) { - Serial.print("Unknow error at address 0x"); - if (addr < 16) - Serial.print("0"); - Serial.println(addr, HEX); - } - } - if (nDevices == 0) - Serial.println("No I2C devices found\n"); - else - Serial.println("done\n"); -} - - - -void playSound() -{ -#ifdef ENABLE_BUZZER - ledcWriteTone(0, 1000); - delay(200); - ledcWriteTone(0, 0); -#endif -} - - - -void lora_init() -{ -#ifdef ENABLE_LOAR - SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_SS); - LoRa.setPins(LORA_SS, LORA_RST, LORA_DI0); - if (!LoRa.begin(BAND)) - Serial.println("LORA Begin FAIL"); - else { - loraBeginOK = true; - Serial.println("LORA Begin PASS"); - } -#endif -} - -void setup() -{ - Serial.begin(115200); - - delay(1000); - - Wire.begin(I2C_SDA, I2C_SCL); - - scanI2Cdevice(); - -#ifdef ENABLE_BUZZER - ledcSetup(0, 1000, 8); - ledcAttachPin(BUZZER_PIN, 0); -#endif - - playSound(); - playSound(); - - if (axp192_found) { - if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) { - Serial.println("AXP192 Begin PASS"); - } else { - Serial.println("AXP192 Begin FAIL"); - } - - // axp.setChgLEDMode(LED_BLINK_4HZ); - - Serial.printf("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE"); - - Serial.println("----------------------------------------"); - - axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); - axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); - axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); - axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); - axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); - axp.setDCDC1Voltage(3300); //esp32 core VDD 3v3 - axp.setLDO2Voltage(3300); //LORA VDD set 3v3 - axp.setLDO3Voltage(3300); //GPS VDD 3v3 - - Serial.printf("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE"); - Serial.printf("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE"); - - - pinMode(PMU_IRQ, INPUT_PULLUP); - attachInterrupt(PMU_IRQ, [] { - pmu_irq = true; - }, FALLING); - - axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); - axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1); - axp.clearIRQ(); - - if (axp.isChargeing()) { - baChStatus = "Charging"; - } - } else { - Serial.println("AXP192 not found"); - } - - button_init(); - - ssd1306_init(); - -#ifdef ENABLE_GPS - Serial1.begin(GPS_BANUD_RATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN); -#endif - -#ifdef ENABLE_LOAR - lora_init(); -#endif - - btnTick.attach_ms(20, button_loop); -} - - - -void loop() -{ - static uint32_t loraMap = 0; - static uint64_t gpsMap = 0; - - if (axp192_found && pmu_irq) { - pmu_irq = false; - axp.readIRQ(); - if (axp.isChargingIRQ()) { - baChStatus = "Charging"; - } else { - baChStatus = "No Charging"; - } - if (axp.isVbusRemoveIRQ()) { - baChStatus = "No Charging"; - } - digitalWrite(2, !digitalRead(2)); - axp.clearIRQ(); - } - switch (program) { - case 0: - while (Serial1.available()) - gps.encode(Serial1.read()); - - if (millis() > 5000 && gps.charsProcessed() < 10) { - snprintf(buff[0], sizeof(buff[0]), "T-Beam GPS"); - snprintf(buff[1], sizeof(buff[1]), "No GPS detected"); - if (!ssd1306_found) { - Serial.println(buff[1]); - } - return; - } - if (!gps.location.isValid()) { - if (millis() - gpsMap > 1000) { - snprintf(buff[0], sizeof(buff[0]), "T-Beam GPS"); - snprintf(buff[1], sizeof(buff[1]), "Positioning(%llu)", gpsSec++); - if (!ssd1306_found) { - Serial.println(buff[1]); - } - gpsMap = millis(); - } - } else { - if (millis() - gpsMap > 1000) { - playSound(); - snprintf(buff[0], sizeof(buff[0]), "UTC:%d:%d:%d", gps.time.hour(), gps.time.minute(), gps.time.second()); - snprintf(buff[1], sizeof(buff[1]), "LNG:%.4f", gps.location.lng()); - snprintf(buff[2], sizeof(buff[2]), "LAT:%.4f", gps.location.lat()); - snprintf(buff[3], sizeof(buff[3]), "satellites:%u", gps.satellites.value()); - if (!ssd1306_found) { - Serial.println(buff[0]); - Serial.println(buff[1]); - Serial.println(buff[2]); - Serial.println(buff[3]); - } - gpsMap = millis(); - } - } - break; - case 1: - snprintf(buff[0], sizeof(buff[0]), "T-Beam Lora Sender"); - if (!loraBeginOK) { - snprintf(buff[1], sizeof(buff[1]), "Lora Begin FAIL"); - if (!ssd1306_found) { - Serial.println(buff[1]); - } - return; - } - - if (millis() - loraMap > 3000) { - LoRa.beginPacket(); - LoRa.print("lora: "); - LoRa.print(loraMap); - LoRa.endPacket(); - snprintf(buff[1], sizeof(buff[1]), "Send %u", loraMap); - loraMap = millis(); - if (!ssd1306_found) { - Serial.println(buff[1]); - } - } - break; - case 2: - if (!loraBeginOK) { - recv = "Lora Begin FAIL"; - if (!ssd1306_found) { - Serial.println(recv); - } - return; - } - snprintf(buff[0], sizeof(buff[0]), "T-Beam Lora Received"); - if (LoRa.parsePacket()) { - recv = ""; - while (LoRa.available()) { - recv += (char)LoRa.read(); - } - if (!ssd1306_found) { - Serial.printf("Lora Received:%s - rssi:%d\n", recv.c_str(), LoRa.packetRssi()); - } - } else { - // if (!ssd1306_found) { - // Serial.println("Wait for received message"); - // delay(500); - // } - } - snprintf(buff[1], sizeof(buff[1]), "rssi:%d", LoRa.packetRssi()); - break; - } - /* - if (ssd1306_found) { - if (ui.update()) { - button_loop(); - } - } else { - button_loop(); - } - */ - if (ssd1306_found) { - if (ui.update()) { - } - } -} +/* +* This factory is just to test LilyGo T-Beam series hardware +* Created by Lewis he +* */ + +#include "board_def.h" +#include +#include +#include "axp20x.h" +#include + +#ifndef AXP192_SLAVE_ADDRESS +#define AXP192_SLAVE_ADDRESS 0x34 +#endif + +SSD1306_OBJECT(); +UBLOX_GPS_OBJECT(); + +AXP20X_Class axp; +uint8_t program = 0; +bool ssd1306_found = false; +bool axp192_found = false; +bool loraBeginOK = false; + +char buff[5][256]; + +uint64_t gpsSec = 0; +bool pmu_irq = false; +#define BUTTONS_MAP {BUTTON_PIN} + +Button2 *pBtns = nullptr; +uint8_t g_btns[] = BUTTONS_MAP; +#define ARRARY_SIZE(a) (sizeof(a) / sizeof(a[0])) + + +String baChStatus = "No charging"; +String recv = ""; + +// flag to indicate that a packet was received +bool receivedFlag = false; + +// disable interrupt when it's not needed +bool enableInterrupt = true; + +RADIO_TYPE radio = new Module(LORA_SS, LORA_DIO1, LORA_RST, LORA_BUSY); + + +/************************************ + * BUTTON + * *********************************/ +void button_callback(Button2 &b) +{ + for (int i = 0; i < ARRARY_SIZE(g_btns); ++i) { + if (pBtns[i] == b) { + if (ssd1306_found) { + ui.nextFrame(); + } + program = program + 1 > 2 ? 0 : program + 1; + if (program == 2) { + Serial.print(F("[RADIO] Starting to listen ... ")); + int state = radio.startReceive(); + if (state == ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + } + } + } +} + +void button_loop() +{ + for (int i = 0; i < ARRARY_SIZE(g_btns); ++i) { + pBtns[i].loop(); + } +} + +void button_init() +{ + uint8_t args = ARRARY_SIZE(g_btns); + pBtns = new Button2 [args]; + for (int i = 0; i < args; ++i) { + pBtns[i] = Button2(g_btns[i]); + pBtns[i].setPressedHandler(button_callback); + } + pBtns[0].setLongClickHandler([](Button2 & b) { + if (ssd1306_found) { + oled.displayOff(); + } + Serial.println("Go to Sleep"); + if (axp192_found) { + axp.setChgLEDMode(AXP20X_LED_OFF); + axp.setPowerOutPut(AXP192_LDO2, AXP202_OFF); + axp.setPowerOutPut(AXP192_LDO3, AXP202_OFF); + axp.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); + // axp.setPowerOutPut(AXP192_DCDC3, AXP202_OFF); + axp.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); + axp.setPowerOutPut(AXP192_EXTEN, AXP202_OFF); + } + + delay(20); + esp_sleep_enable_ext1_wakeup(BUTTON_PIN_MASK, ESP_EXT1_WAKEUP_ALL_LOW); + esp_deep_sleep_start(); + }); +} + +void msOverlay(OLEDDisplay *display, OLEDDisplayUiState *state) +{ + static char volbuffer[128]; + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_10); + + display->drawString(0, 0, baChStatus); + + if (axp.isBatteryConnect()) { + snprintf(volbuffer, sizeof(volbuffer), "%.2fV/%.2fmA", axp.getBattVoltage() / 1000.0, axp.isChargeing() ? axp.getBattChargeCurrent() : axp.getBattDischargeCurrent()); + display->drawString(62, 0, volbuffer); + } else { + multi_heap_info_t info; + heap_caps_get_info(&info, MALLOC_CAP_INTERNAL); + snprintf(volbuffer, sizeof(volbuffer), "%u/%uKB", info.total_allocated_bytes / 1024, info.total_free_bytes / 1024); + display->drawString(75, 0, volbuffer); + } +} + +void drawFrame1(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +{ + + display->setFont(ArialMT_Plain_10); + display->setTextAlignment(TEXT_ALIGN_CENTER); + + if (!gps.location.isValid()) { + display->drawString(64 + x, 11 + y, buff[0]); + display->drawString(64 + x, 22 + y, buff[1]); + } else { + display->drawString(64 + x, 11 + y, buff[0]); + display->drawString(64 + x, 22 + y, buff[1]); + display->drawString(64 + x, 33 + y, buff[2]); + display->drawString(64 + x, 44 + y, buff[3]); + } +} + +void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +{ + display->setFont(ArialMT_Plain_10); + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->drawString(64 + x, 11 + y, buff[0]); + display->drawString(64 + x, 22 + y, buff[1]); +} + +void drawFrame3(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +{ + display->setFont(ArialMT_Plain_10); + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->drawString(64 + x, 9 + y, buff[0]); + display->drawString(64 + x, 22 + y, recv == "" ? "No message" : recv); + display->drawString(64 + x, 35 + y, buff[1]); +} + + +FrameCallback frames[] = {drawFrame1, drawFrame2, drawFrame3}; +OverlayCallback overlays[] = { msOverlay }; + +void ssd1306_init() +{ +#ifdef ENABLE_SSD1306 + if (!ssd1306_found) { + Serial.println("SSD1306 not found"); + return; + } + if (oled.init()) { + oled.flipScreenVertically(); + oled.setFont(ArialMT_Plain_16); + oled.setTextAlignment(TEXT_ALIGN_CENTER); + } else { + Serial.println("SSD1306 Begin FAIL"); + } + Serial.println("SSD1306 Begin PASS"); + ui.setTargetFPS(30); + ui.disableAutoTransition(); + ui.setIndicatorPosition(BOTTOM); + ui.setIndicatorDirection(LEFT_RIGHT); + ui.setFrameAnimation(SLIDE_LEFT); + ui.setFrames(frames, ARRARY_SIZE(frames)); + if (axp192_found) { + ui.setOverlays(overlays, ARRARY_SIZE(overlays)); + } +#endif +} + + + +void scanI2Cdevice(void) +{ + byte err, addr; + int nDevices = 0; + for (addr = 1; addr < 127; addr++) { + Wire.beginTransmission(addr); + err = Wire.endTransmission(); + if (err == 0) { + Serial.print("I2C device found at address 0x"); + if (addr < 16) + Serial.print("0"); + Serial.print(addr, HEX); + Serial.println(" !"); + nDevices++; + + if (addr == SSD1306_ADDRESS) { + ssd1306_found = true; + Serial.println("ssd1306 display found"); + } + if (addr == AXP192_SLAVE_ADDRESS) { + axp192_found = true; + Serial.println("axp192 PMU found"); + } + } else if (err == 4) { + Serial.print("Unknow error at address 0x"); + if (addr < 16) + Serial.print("0"); + Serial.println(addr, HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found\n"); + else + Serial.println("done\n"); +} + +void playSound() +{ +#ifdef ENABLE_BUZZER + ledcWriteTone(0, 1000); + delay(200); + ledcWriteTone(0, 0); +#endif +} + +// this function is called when a complete packet +// is received by the module +// IMPORTANT: this function MUST be 'void' type +// and MUST NOT have any arguments! +void setFlag(void) +{ + // check if the interrupt is enabled + if (!enableInterrupt) { + return; + } + // we got a packet, set the flag + receivedFlag = true; +} + +void lora_init() +{ + SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_SS); + Serial.print(F("[Radio] Initializing ... ")); + int state = radio.begin(BAND); + if (state == ERR_NONE) { + loraBeginOK = true; + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + + // set the function that will be called + // when new packet is received + radio.setDio1Action(setFlag); + +} + +void setup() +{ + Serial.begin(115200); + + delay(1000); + + Wire.begin(I2C_SDA, I2C_SCL); + + scanI2Cdevice(); + +#ifdef ENABLE_BUZZER + ledcSetup(0, 1000, 8); + ledcAttachPin(BUZZER_PIN, 0); +#endif + + playSound(); + playSound(); + + if (axp192_found) { + if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) { + Serial.println("AXP192 Begin PASS"); + } else { + Serial.println("AXP192 Begin FAIL"); + } + + // axp.setChgLEDMode(LED_BLINK_4HZ); + + Serial.printf("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE"); + + Serial.println("----------------------------------------"); + + axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); + axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); + axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + axp.setDCDC1Voltage(3300); //esp32 core VDD 3v3 + axp.setLDO2Voltage(3300); //LORA VDD set 3v3 + axp.setLDO3Voltage(3300); //GPS VDD 3v3 + + Serial.printf("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE"); + Serial.printf("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE"); + + + pinMode(PMU_IRQ, INPUT_PULLUP); + attachInterrupt(PMU_IRQ, [] { + pmu_irq = true; + }, FALLING); + + axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); + axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1); + axp.clearIRQ(); + + if (axp.isChargeing()) { + baChStatus = "Charging"; + } + } else { + Serial.println("AXP192 not found"); + } + + button_init(); + + ssd1306_init(); + +#ifdef ENABLE_GPS + Serial1.begin(GPS_BANUD_RATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN); +#endif + +#ifdef ENABLE_LOAR + lora_init(); +#endif + +} + + + +void loop() +{ + button_loop(); + + static uint32_t loraMap = 0; + static uint64_t gpsMap = 0; + + if (axp192_found && pmu_irq) { + pmu_irq = false; + axp.readIRQ(); + if (axp.isChargingIRQ()) { + baChStatus = "Charging"; + } else { + baChStatus = "No Charging"; + } + if (axp.isVbusRemoveIRQ()) { + baChStatus = "No Charging"; + } + digitalWrite(2, !digitalRead(2)); + axp.clearIRQ(); + } + switch (program) { + case 0: + while (Serial1.available()) + gps.encode(Serial1.read()); + + if (millis() > 5000 && gps.charsProcessed() < 10) { + snprintf(buff[0], sizeof(buff[0]), "T-Beam GPS"); + snprintf(buff[1], sizeof(buff[1]), "No GPS detected"); + if (!ssd1306_found) { + Serial.println(buff[1]); + } + return; + } + if (!gps.location.isValid()) { + if (millis() - gpsMap > 1000) { + snprintf(buff[0], sizeof(buff[0]), "T-Beam GPS"); + snprintf(buff[1], sizeof(buff[1]), "Positioning(%llu)", gpsSec++); + if (!ssd1306_found) { + Serial.println(buff[1]); + } + gpsMap = millis(); + } + } else { + if (millis() - gpsMap > 1000) { + playSound(); + snprintf(buff[0], sizeof(buff[0]), "UTC:%d:%d:%d", gps.time.hour(), gps.time.minute(), gps.time.second()); + snprintf(buff[1], sizeof(buff[1]), "LNG:%.4f", gps.location.lng()); + snprintf(buff[2], sizeof(buff[2]), "LAT:%.4f", gps.location.lat()); + snprintf(buff[3], sizeof(buff[3]), "satellites:%u", gps.satellites.value()); + if (!ssd1306_found) { + Serial.println(buff[0]); + Serial.println(buff[1]); + Serial.println(buff[2]); + Serial.println(buff[3]); + } + gpsMap = millis(); + } + } + break; + case 1: + snprintf(buff[0], sizeof(buff[0]), "T-Beam Lora Sender"); + if (!loraBeginOK) { + snprintf(buff[1], sizeof(buff[1]), "Lora Begin FAIL"); + if (!ssd1306_found) { + Serial.println(buff[1]); + } + return; + } + + if (millis() - loraMap > 3000) { + int transmissionState = ERR_NONE; + transmissionState = radio.startTransmit(String(loraMap).c_str()); + // check if the previous transmission finished + if (receivedFlag) { + // disable the interrupt service routine while + // processing the data + enableInterrupt = false; + // reset flag + receivedFlag = false; + if (transmissionState == ERR_NONE) { + // packet was successfully sent + Serial.println(F("transmission finished!")); + // NOTE: when using interrupt-driven transmit method, + // it is not possible to automatically measure + // transmission data rate using getDataRate() + + } else { + Serial.print(F("failed, code ")); + Serial.println(transmissionState); + } + // wait a second before transmitting again + // delay(1000); + + // send another one + Serial.print(F("[RADIO] Sending another packet ... ")); + + // you can transmit C-string or Arduino string up to + // 256 characters long + transmissionState = radio.startTransmit(String(loraMap).c_str()); + + // you can also transmit byte array up to 256 bytes long + /* + byte byteArr[] = {0x01, 0x23, 0x45, 0x67, + 0x89, 0xAB, 0xCD, 0xEF}; + int state = radio.startTransmit(byteArr, 8); + */ + + // we're ready to send more packets, + // enable interrupt service routine + enableInterrupt = true; + } + snprintf(buff[1], sizeof(buff[1]), "Send %u", loraMap); + loraMap = millis(); + if (!ssd1306_found) { + Serial.println(buff[1]); + } + } + break; + case 2: + if (!loraBeginOK) { + recv = "Lora Begin FAIL"; + if (!ssd1306_found) { + Serial.println(recv); + } + return; + } + snprintf(buff[0], sizeof(buff[0]), "T-Beam Lora Received"); + + // check if the flag is set + if (receivedFlag) { + // disable the interrupt service routine while + // processing the data + enableInterrupt = false; + + // reset flag + receivedFlag = false; + + // you can read received data as an Arduino String + int state = radio.readData(recv); + + // you can also read received data as byte array + /* + byte byteArr[8]; + int state = radio.readData(byteArr, 8); + */ + + if (state == ERR_NONE) { + // packet was successfully received + Serial.println(F("[RADIO] Received packet!")); + + // print data of the packet + Serial.print(F("[RADIO] Data:\t\t")); + Serial.println(recv); + + // print RSSI (Received Signal Strength Indicator) + Serial.print(F("[RADIO] RSSI:\t\t")); + Serial.print(radio.getRSSI()); + Serial.println(F(" dBm")); + snprintf(buff[1], sizeof(buff[1]), "rssi:%.2f dBm", radio.getRSSI()); + + // print SNR (Signal-to-Noise Ratio) + Serial.print(F("[RADIO] SNR:\t\t")); + Serial.print(radio.getSNR()); + Serial.println(F(" dB")); + + } else if (state == ERR_CRC_MISMATCH) { + // packet was received, but is malformed + Serial.println(F("CRC error!")); + + } else { + // some other error occurred + Serial.print(F("failed, code ")); + Serial.println(state); + + } + + // put module back to listen mode + radio.startReceive(); + + // we're ready to receive more packets, + // enable interrupt service routine + enableInterrupt = true; + } + break; + } + if (ssd1306_found) { + ui.update(); + } +} diff --git a/src/board_def.h b/src/board_def.h index 3f26afb..198b3fe 100644 --- a/src/board_def.h +++ b/src/board_def.h @@ -1,3 +1,7 @@ +/* +* This factory is just to test LilyGo T-Beam series hardware +* Created by Lewis he +* */ #ifndef BOARD_DEF_H #define BOARD_DEF_H @@ -8,8 +12,7 @@ #define ENABLE_GPS #define ENABLE_LOAR - -#define SSD1306_ADDRESS 0x3c +#define SSD1306_ADDRESS 0x3C #ifdef ENABLE_SSD1306 #include "SSD1306.h" #include "OLEDDisplayUi.h" @@ -20,20 +23,38 @@ #endif #ifdef ENABLE_LOAR -#include +#include -#define LORA_PERIOD 868 +/* +Replace the model according to the actual situation + +RADIO_TYPE option: + - SX1278 + - SX1276 + - SX1262 +*/ +#define RADIO_TYPE SX1262 + +/* +Fill in the frequency according to the actual situation +LORA_PERIOD option: + - 433,470,868,915 +*/ +#define LORA_PERIOD 915 + + +#define LORA_SCK 5 +#define LORA_MISO 19 +#define LORA_MOSI 27 +#define LORA_SS 18 +#define LORA_DI0 26 +#define LORA_RST 23 +#define LORA_DIO1 33 +#define LORA_BUSY 32 -#define LORA_SCK 5 -#define LORA_MISO 19 -#define LORA_MOSI 27 -#define LORA_SS 18 -#define LORA_DI0 26 -#define LORA_RST 23 #endif -//GPS模块 #ifdef ENABLE_GPS #include #define UBLOX_GPS_OBJECT() TinyGPSPlus gps @@ -57,13 +78,15 @@ UBLOX_GPS_OBJECT() #ifdef ENABLE_LOAR #if LORA_PERIOD == 433 -#define BAND 433E6 +#define BAND 433.0 #elif LORA_PERIOD == 868 -#define BAND 868E6 +#define BAND 868.0 #elif LORA_PERIOD == 915 -#define BAND 915E6 +#define BAND 915.0 +#elif LORA_PERIOD == 470 +#define BAND 470.0 #else -#define BAND 433E6 +#define BAND 433.0 #endif #endif @@ -71,8 +94,6 @@ UBLOX_GPS_OBJECT() #define I2C_SDA 21 #define I2C_SCL 22 #define PMU_IRQ 35 -#define GPS_POWER_CTRL_CH 3 -#define LORA_POWER_CTRL_CH 2 #define ENABLE_BUZZER #define BUZZER_PIN 4