/* Ukazkovy program Meteostanice_LoRa_433_MHz od OK1FCB 2026 Do nataveni Arduino IDE pridej URL https://dl.espressif.com/dl/package_esp32_index.json V Arduino IDE instaluj knihovnu esp32 a vyber desku TTGO LoRa32-OLED */ #include // Knihovna pro TTGO LoRa32-OLED #include // Knihovna pro Sensor #include // Knihovna pro OLED #define pin_baterie 35 // Pin ADC1_0 pro mereni napeti baterie #define pin_oled_on 4 // Pin pro ovladani OLED on/off #define pin_tx_led 25 // Pin integrovane zelene LED pro signalizaci vysilani #define vref 3.445f // Kalibrace referencniho napeti AD prevodniku #define vyska 260 // Vyska sondy pro prepocet tlaku na hladinu more const char* station = "OK1XXX-1>APRS:!5022.67N/01604.22E_"; // Sem zadej svoji znacku a souradnice odectene z mapy na https://aprs.fi/ int doba_spanku = 15; // Doba spanku (perioda vysilani) v minutach Adafruit_SSD1306 display(128, 64, &Wire, -1); // Nastaveni OLED (vyska, sirka) Adafruit_BME280 bme; void setupLoRa() { // Nastaveni LoRa protokolu SPI.begin(5, 19, 27, 18); // Nastaveni SPI (SCK, MISO, MOSI, SS) LoRa.setPins(18, 23, 26); // Nastaveni LoRa (SS, RST, DIO0) LoRa.setTxPower(20, true); // Maximalni vykon modulu je 20 dBm = 100 mW (pozor, max. vykon pouze pro amaterskou sluzbu, jinak v pasmu 433 MHz maximalne 10 mW ERP jako bezlicencni SRD/ISM provoz)! if (!LoRa.begin(433775E3)) { // Nastaveni kmitoctu vysilace v Hz (pozor, sdilene pasmo amaterska sluzba a SRD)! Serial.println("Inicializace LoRa selhala"); while (1) ; } LoRa.setSpreadingFactor(12); // SF12 - kolik symbolu se pouzije k zakodovani jednoho bitu LoRa.setSignalBandwidth(125E3); // Sirka pasma v Hz LoRa.setCodingRate4(5); // Forward Error Correction (FEC) 4/5 az 4/8 (cim vyssi jmenovatel, tim vic redundance) LoRa.enableCrc(); } void sendMsg(float batv, float tF, float pres, float hum) { // Naformatovani APRS zpravy digitalWrite(pin_tx_led, digitalRead(pin_oled_on)); // Indikace vysilani zelenou LED (jen pokud je OLED zapnuty) char msg[128]; // Pole znaku msg o velikosti 128 bajtu char tempStr[5], humStr[4], presStr[8], batStr[11]; // Velikost pole vzdy + 1 snprintf(batStr, sizeof(batStr), "BAT %.2f V", batv); snprintf(tempStr, sizeof(tempStr), "t%03d", (int)tF); snprintf(humStr, sizeof(humStr), "h%02d", (int)hum >= 100 ? 0 : (int)hum); snprintf(presStr, sizeof(presStr), "b%05d", (int)pres); snprintf(msg, sizeof(msg), "%s.../...%s%s%s %s %s", station, tempStr, humStr, presStr, batStr, "Test T3 LoRa32 433,775 MHz"); // Sestavi zpravu bez mereni vetru a srazek // Priklad paketu: OK1XXX-1>APRS:!5022.67N/01604.22E_.../...t075h39b09860 BAT 4.17 V Test T3 LoRa32 433,775 MHz LoRa.beginPacket(); LoRa.write('<'); LoRa.write(0xFF); LoRa.write(0x01); LoRa.print(msg); LoRa.endPacket(); LoRa.sleep(); Serial.println(msg); // Tisk pro kontrolu na seriovy monitor digitalWrite(pin_tx_led, LOW); } void setup() { setCpuFrequencyMhz(40); gpio_deep_sleep_hold_dis(); // Globalne vypne hold vsech pinu po probuzeni Serial.begin(115200); while (!Serial) ; pinMode(pin_tx_led, OUTPUT); pinMode(pin_oled_on, INPUT_PULLUP); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Inicializace OLED if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) Serial.println("OLED nenalezen"); display.setRotation(0); // Nastaveni rotace displeje (0,1,2,3 po 90 st.) display.setTextSize(2); // Velikost textu display.setTextColor(SSD1306_WHITE); // Barva textu display.cp437(true); // Pouzij znakovou sadu CP437 display.clearDisplay(); display.display(); // OLED provede nastaveni bool oledOn = digitalRead(pin_oled_on); display.ssd1306_command(oledOn ? SSD1306_DISPLAYON : SSD1306_DISPLAYOFF); // Je-li oledOn 1, potom zapni OLED setupLoRa(); if (!bme.begin(0x76)) Serial.println("BME280 nenalezen"); float batv = (vref * analogRead(pin_baterie)) / 4095.0f * 2.0f; float tC = bme.readTemperature(); float tF = tC * 1.8f + 32.0f; // Prepocet deg C na deg F float pres = bme.readPressure() / pow(1.0f - vyska / 44330.0f, 5.255f) / 10.0f; // Prepocet tlaku na hladinu more float hum = bme.readHumidity(); if (oledOn) { display.clearDisplay(); display.setCursor(0, 0); display.printf("T: %.1f %cC", tC, 248); // znak 248 je pro zobraceni znaku deg display.setTextSize(1); display.setCursor(0, 30); display.printf("P: %.1f mbar", pres); display.setCursor(0, 40); display.printf("H: %.0f %%", hum); // %% pro tisk znaku "%" display.setCursor(0, 50); display.printf("B: %.2f V", batv); display.display(); // OLED proved nastaveni } sendMsg(batv, tF, pres, hum); // Posle zpravu esp_sleep_enable_timer_wakeup(doba_spanku * 60E6); // Nastavi cas probuzeni v us Serial.printf("Doba spanku nastavena na %lu minut\n", doba_spanku); // Tisk pro kontrolu na seriovy monitor esp_deep_sleep_start(); } void loop() {}