Daftar Isi:
- Perlengkapan
- Langkah 1: Perpustakaan
- Langkah 2: Pinout
- Langkah 3: Pin AUX
- Langkah 4: Skema Terhubung Penuh Esp8266
- Langkah 5: Skema Arduino Terhubung Sepenuhnya
- Langkah 6: Perpustakaan: Konstruktor
- Langkah 7: Mulai
- Langkah 8: Konfigurasi dan Metode Informasi
- Langkah 9: Wadah Respons
- Langkah 10: Opsi Konfigurasi Dasar
- Langkah 11: Kirim Terima Pesan
- Langkah 12: Mode Transmisi Normal
- Langkah 13: Kelola Struktur
- Langkah 14: Mode Tetap Alih-alih Mode Normal
- Langkah 15: Terima kasih
Video: Komunikasi Nirkabel LoRa 3Km hingga 8Km Dengan Perangkat E32 (sx1278/sx1276) Berbiaya Rendah untuk Arduino, Esp8266 atau Esp32: 15 Langkah
2024 Pengarang: John Day | [email protected]. Terakhir diubah: 2024-01-30 09:53
Saya membuat perpustakaan untuk mengelola EBYTE E32 berdasarkan perangkat LoRa seri Semtech, perangkat yang sangat kuat, sederhana dan murah.
Anda dapat menemukan versi 3Km di sini, versi 8Km di sini
Mereka dapat bekerja pada jarak 3000m hingga 8000m, dan mereka memiliki banyak fitur dan parameter. Jadi saya membuat perpustakaan ini untuk menyederhanakan penggunaan.
Ini adalah solusi untuk mengambil data dari sensor metropolitan atau untuk mengontrol drone.
Perlengkapan
Arduino UNO
Wemos D1 mini
LoRa E32 TTL 100 versi 3Km
Versi LoRa E32 TTL 1W 8Km
Langkah 1: Perpustakaan
Anda dapat menemukan perpustakaan saya di sini.
Untuk mengunduh.
Klik tombol UNDUH di sudut kanan atas, ganti nama folder yang tidak terkompresi LoRa_E32.
Periksa apakah folder LoRa_E32 berisi LoRa_E32.cpp dan LoRa_E32.h.
Tempatkan folder perpustakaan LoRa_E32 folder /libraries/ Anda. Anda mungkin perlu membuat subfolder perpustakaan jika ini adalah perpustakaan pertama Anda.
Mulai ulang IDE.
Langkah 2: Pinout
Seperti yang Anda lihat, Anda dapat mengatur berbagai mode melalui pin M0 dan M1.
Ada beberapa pin yang dapat digunakan secara statis, tetapi jika Anda menghubungkannya ke mikrokontroler dan mengonfigurasinya di perpustakaan, Anda mendapatkan kinerja dan Anda dapat mengontrol semua mode melalui perangkat lunak, tetapi kami akan menjelaskan lebih baik selanjutnya.
Langkah 3: Pin AUX
Seperti yang sudah saya katakan Tidak penting untuk menghubungkan semua pin ke output mikrokontroler, Anda dapat menempatkan pin M0 dan M1 ke TINGGI atau RENDAH untuk mendapatkan konfigurasi yang diinginkan, dan jika Anda tidak menghubungkan AUX, perpustakaan menetapkan penundaan yang wajar untuk memastikan bahwa operasi selesai.
pin AUX
Saat mentransmisikan data dapat digunakan untuk membangunkan MCU eksternal dan mengembalikan TINGGI pada transfer data selesai.
Saat menerima AUX menjadi LOW dan kembali HIGH saat buffer kosong.
Ini juga digunakan untuk memeriksa sendiri untuk mengembalikan operasi normal (pada mode power-on dan sleep/program).
Langkah 4: Skema Terhubung Penuh Esp8266
Skema koneksi esp8266 lebih sederhana karena bekerja pada tegangan yang sama dengan komunikasi logis (3.3v).
Penting untuk menambahkan resistor pull-up (4, 7Kohm) untuk mendapatkan stabilitas yang baik.
Langkah 5: Skema Arduino Terhubung Sepenuhnya
Tegangan kerja Arduino adalah 5v, jadi kita perlu menambahkan pembagi tegangan pada pin RX M0 dan M1 dari modul LoRa untuk mencegah kerusakan, Anda bisa mendapatkan informasi lebih lanjut di sini Pembagi tegangan: kalkulator dan aplikasi.
Anda dapat menggunakan resistor 2Kohm ke GND dan 1Kohm dari sinyal daripada disatukan di RX.
Langkah 6: Perpustakaan: Konstruktor
Saya membuat satu set konstruktor yang cukup banyak, karena kita dapat memiliki lebih banyak opsi dan situasi untuk dikelola.
LoRa_E32(byte rxPin, byte txPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
LoRa_E32(byte rxPin, byte txPin, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); LoRa_E32(byte rxPin, byte txPin, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
Set konstruktor pertama dibuat untuk mendelegasikan pengelolaan Serial dan pin lainnya ke perpustakaan.
rxPin dan txPin adalah pin untuk terhubung ke UART dan mereka wajib.
auxPin adalah pin yang memeriksa status operasi, transmisi, dan penerimaan (kita akan menjelaskan lebih baik selanjutnya), pin itu Tidak wajib, jika Anda tidak menyetelnya, saya menerapkan penundaan untuk mengizinkan operasi menyelesaikan sendiri (dengan latensi).
m0pin dan m1Pin adalah pin untuk mengubah MODE operasi (lihat tabel di atas), saya pikir pin ini dalam "produksi" akan terhubung langsung HIGH atau LOW, tetapi untuk pengujian mereka berguna untuk dikelola oleh perpustakaan.
bpsRate adalah boudrate SoftwareSerial biasanya adalah 9600 (satu-satunya baud rate dalam mode programmin/sleep)
Contoh sederhananya adalah
#sertakan "LoRa_E32.h"LoRa_E32 e32ttl100(2, 3); // RX, TX // LoRa_E32 e32ttl100(2, 3, 5, 6, 7); // RX, TX
Kita dapat menggunakan SoftwareSerial secara langsung dengan konstruktor lain
LoRa_E32(Serial Perangkat Keras*, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
LoRa_E32(HardwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
LoRa_E32(Serial Perangkat Keras*, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
Contoh atas dengan konstruktor ini dapat dilakukan seperti itu.
#sertakan #sertakan "LoRa_E32.h"
SoftwareSerial mySerial(2, 3); // RX, TX
LoRa_E32 e32ttl100(&mySerial);
// LoRa_E32 e32ttl100(&mySerial, 5, 7, 6);
Set konstruktor terakhir adalah mengizinkan untuk menggunakan HardwareSerial alih-alih SoftwareSerial.
LoRa_E32(SoftwareSerial* serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
LoRa_E32(SoftwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
LoRa_E32(SoftwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
Langkah 7: Mulai
Perintah begin digunakan untuk memulai Serial dan pin dalam mode input dan output.
batal mulai();
dalam eksekusi adalah
// Mulai semua pin dan UART
e32ttl100.begin();
Langkah 8: Konfigurasi dan Metode Informasi
Ada satu set metode untuk mengelola konfigurasi dan mendapatkan informasi perangkat.
ResponseStructContainer getConfiguration();
ResponseStatus setConfiguration(Konfigurasi konfigurasi, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);
ResponseStructContainer getModuleInformation();
void printParameters(konfigurasi Konfigurasi struct);
ResponseStatus resetModule();
Langkah 9: Wadah Respons
Untuk menyederhanakan pengelolaan respons, saya membuat satu set wadah, bagi saya sangat berguna untuk mengelola kesalahan dan mengembalikan data umum.
Status Tanggapan
Ini adalah wadah status dan memiliki 2 titik masuk sederhana, dengan ini Anda bisa mendapatkan kode status dan deskripsi kode status
Serial.println(c.getResponseDescription()); // Deskripsi kode
Serial.println(c.kode); // 1 jika Sukses
Kodenya adalah
SUKSES = 1, ERR_UNKNOWN, ERR_NOT_DUKUNGAN, ERR_NOT_IMPLEMENT, ERR_NOT_INITIAL, ERR_INVALID_PARAM, ERR_DATA_SIZE_NOT_MATCH, ERR_BUF_TOO_SMALL, ERR_TIMEOUT, ERR_HARDWARE, ERR_HEAD_NOT_RECOGNIZED
ResponContainer
Wadah ini dibuat untuk mengelola respons String dan memiliki 2 titik masuk.
data dengan string yang dikembalikan dari pesan dan status merupakan turunan dari RepsonseStatus.
ResponseContainer rs = e32ttl.receiveMessage();
Pesan string = rs.data;
Serial.println(rs.status.getResponseDescription());
Serial.println(pesan);
ResponseStructContainer
Ini adalah wadah yang lebih "kompleks", saya menggunakan ini untuk mengelola struktur, Ini memiliki titik masuk yang sama dengan ResponseContainer tetapi data adalah penunjuk kosong untuk mengelola struktur kompleks.
ResponseStructContainer c;
c = e32ttl100.getConfiguration();// Sangat penting untuk mendapatkan pointer konfigurasi sebelum semua operasi lainnya
Konfigurasi konfigurasi = *(Konfigurasi*) c.data;
Serial.println(c.status.getResponseDescription());
Serial.println(c.status.code);
getConfiguration dan setConfiguration
Metode pertama adalah getConfiguration, Anda dapat menggunakannya untuk mengambil semua data yang tersimpan di perangkat.
ResponseStructContainer getConfiguration();
Berikut contoh penggunaan.
ResponseStructContainer c;
c = e32ttl100.getConfiguration();// Sangat penting untuk mendapatkan pointer konfigurasi sebelum semua operasi lainnya
Konfigurasi konfigurasi = *(Konfigurasi*) c.data;
Serial.println(c.status.getResponseDescription());
Serial.println(c.status.code);
Serial.println(configuration. SPED.getUARTBaudRate());
Struktur konfigurasi memiliki semua data pengaturan, dan saya menambahkan serangkaian fungsi untuk mendapatkan semua deskripsi data tunggal.
konfigurasi. ADDL = 0x0; // Bagian pertama dari addressconfiguration. ADDH = 0x1; // Bagian kedua dari konfigurasi alamat. CHAN = 0x19;// Konfigurasi saluran. OPTION.fec = FEC_0_OFF; // Konfigurasi sakelar koreksi kesalahan maju. OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; // Konfigurasi mode transmisi. OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS; // Konfigurasi manajemen pull-up. OPTION.transmissionPower = POWER_17; // konfigurasi daya transmisi dBm. OPTION.wirelessWakeupTime = WAKE_UP_1250; // Tunggu waktu untuk konfigurasi bangun. SPED.airDataRate = AIR_DATA_RATE_011_48; // Konfigurasi kecepatan data udara. SPED.uartBaudRate = UART_BPS_115200; // Konfigurasi kecepatan baud komunikasi. SPED.uartParity = MODE_00_8N1; // bit paritas
Anda memiliki fungsi yang setara untuk semua atribut untuk mendapatkan semua deskripsi:
Serial.print(F("Chan: ")); Serial.print(configuration. CHAN, DEC); Serial.print(" -> "); Serial.println(configuration.getChannelDescription());Serial.println(F(" ")); Serial.print(F("SpeedParityBit: ")); Serial.print(configuration. SPED.uartParity, BIN);Serial.print(" -> "); Serial.println(configuration. SPED.getUARTParityDescription()); Serial.print(F("KecepatanUARTDatte: ")); Serial.print(configuration. SPED.uartBaudRate, BIN);Serial.print(" -> "); Serial.println(configuration. SPED.getUARTBaudRate()); Serial.print(F("KecepatanAirDataRate: ")); Serial.print(configuration. SPED.airDataRate, BIN);Serial.print(" -> "); Serial.println(configuration. SPED.getAirDataRate()); Serial.print(F("PilihanTrans: ")); Serial.print(configuration. OPTION.fixedTransmission, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getFixedTransmissionDescription()); Serial.print(F("Pilihan Tarik: ")); Serial.print(configuration. OPTION.ioDriveMode, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getIODroveModeDescription()); Serial.print(F("Pilihan Bangun: ")); Serial.print(configuration. OPTION.wirelessWakeupTime, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getWirelessWakeUPTimeDescription()); Serial.print(F("PilihanFEC: ")); Serial.print(configuration. OPTION.fec, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getFECDescription()); Serial.print(F("Kekuatan Pilihan: ")); Serial.print(configuration. OPTION.transmissionPower, BIN);Serial.print(" -> "); Serial.println(configuration. OPTION.getTransmissionPowerDescription());
Dengan cara yang sama setConfiguration menginginkan struktur konfigurasi, jadi saya pikir cara yang lebih baik untuk mengelola konfigurasi adalah dengan mengambil yang sekarang, menerapkan satu-satunya perubahan yang Anda butuhkan dan mengaturnya lagi.
ResponseStatus setConfiguration(Konfigurasi konfigurasi, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);
konfigurasi adalah struktur yang ditampilkan sebelumnya, saveType mengizinkan Anda untuk memilih jika perubahan menjadi permanen hanya untuk sesi saat ini.
ResponseStructContainer c;c = e32ttl100.getConfiguration(); // Penting untuk mendapatkan pointer konfigurasi sebelum semua operasi lainnya Konfigurasi konfigurasi = *(Konfigurasi*) c.data; Serial.println(c.status.getResponseDescription()); Serial.println(c.status.code); printParameters(konfigurasi); konfigurasi. ADDL = 0x0; konfigurasi. ADDH = 0x1; konfigurasi. CHAN = 0x19; konfigurasi. OPTION.fec = FEC_0_OFF; konfigurasi. OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; konfigurasi. OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS; konfigurasi. OPTION.transmissionPower = POWER_17; konfigurasi. OPTION.wirelessWakeupTime = WAKE_UP_1250; konfigurasi. SPED.airDataRate = AIR_DATA_RATE_011_48; konfigurasi. SPED.uartBaudRate = UART_BPS_115200; konfigurasi. SPED.uartParity = MODE_00_8N1; // Atur konfigurasi yang diubah dan atur agar tidak menahan konfigurasi ResponseStatus rs = e32ttl100.setConfiguration(configuration, WRITE_CFG_PWR_DWN_LOSE); Serial.println(rs.getResponseDescription()); Serial.println(rs.code); printParameters(konfigurasi);
Semua parameter dikelola sebagai konstan:
Langkah 10: Opsi Konfigurasi Dasar
Langkah 11: Kirim Terima Pesan
Pertama kita harus memperkenalkan metode sederhana namun berguna untuk memeriksa apakah ada sesuatu di buffer penerima
int tersedia();
Ini hanya mengembalikan berapa banyak byte yang Anda miliki di aliran saat ini.
Langkah 12: Mode Transmisi Normal
Mode transmisi Normal/Transparan digunakan untuk mengirim pesan ke semua perangkat dengan alamat dan saluran yang sama.
Ada banyak metode untuk mengirim/menerima pesan, kami akan menjelaskan secara rinci:
ResponseStatus sendMessage(const String pesan);
ResponseContainer menerimaMessage();
Metode pertama adalah sendMessage dan digunakan untuk mengirim String ke perangkat dalam mode Normal.
ResponseStatus rs = e32ttl.sendMessage("Prova");Serial.println(rs.getResponseDescription());
Perangkat lain cukup lakukan di loop
if (e32ttl.available() > 1){ResponseContainer rs = e32ttl.receiveMessage(); Pesan string = rs.data; // Pertama dapatkan data Serial.println(rs.status.getResponseDescription()); Serial.println(pesan); }
Langkah 13: Kelola Struktur
Jika Anda ingin mengirim struktur yang kompleks, Anda dapat menggunakan metode ini
ResponseStatus sendMessage(const void *message, const uint8_t size);ResponseStructContainer acceptMessage(const uint8_t size);
Ini digunakan untuk mengirim strucutre, misalnya:
struct Messaggione {tipe karakter[5]; pesan karakter[8]; bool mitico; }; struct Messaggione messaggione = {"TEMP", "Peple", true}; ResponseStatus rs = e32ttl.sendMessage(&messaggione, sizeof(Messaggione)); Serial.println(rs.getResponseDescription());
dan sisi lain Anda dapat menerima pesan jadi
ResponseStructContainer rsc = e32ttl.receiveMessage(sizeof(Messaggione));struct Messaggione messaggione = *(Messaggione*) rsc.data; Serial.println(messaggion.message); Serial.println(messaggione.mitico);
Baca struktur parsial
Jika Anda ingin membaca bagian pertama dari pesan untuk mengelola lebih banyak jenis struktur, Anda dapat menggunakan metode ini.
ResponseContainer menerimaInitialMessage(ukuran const uint8_t);
Saya membuatnya untuk menerima string dengan tipe atau lainnya untuk mengidentifikasi struktur yang akan dimuat.
struct Messaggione { // Struktur parsial tanpa pesan typechar[8]; bool mitico; }; tipe karakter[5]; // bagian pertama dari struktur ResponseContainer rs = e32ttl.receiveInitialMessage(sizeof(type)); // Masukkan string ke dalam array char (tidak diperlukan) memcpy (type, rs.data.c_str(), sizeof(type)); Serial.println("JENIS BACA: "); Serial.println(rs.status.getResponseDescription()); Serial.println(tipe); // Baca sisa struktur ResponseStructContainer rsc = e32ttl.receiveMessage(sizeof(Messaggione)); struct Pesan Messaggion = *(Messaggione*) rsc.data;
Langkah 14: Mode Tetap Alih-alih Mode Normal
Dengan cara yang sama saya membuat satu set metode untuk digunakan dengan transmisi tetap
Transmisi tetap
Anda hanya perlu mengubah metode pengiriman, karena perangkat tujuan tidak menerima pembukaan dengan Alamat dan Saluran quando settato il mode tetap.
Jadi untuk pesan String yang Anda miliki
ResponseStatus sendFixedMessage(byte ADDL, byte ADDH, byte CHAN, const String pesan);ResponseStatus sendBroadcastFixedMessage(byte CHAN, const pesan String);
dan untuk struktur yang Anda miliki
ResponseStatus sendFixedMessage(byte ADDL, byte ADDH, byte CHAN, const void *pesan, ukuran const uint8_t);ResponseStatus sendBroadcastFixedMessage(byte CHAN, const void *pesan, ukuran const uint8_t);
Berikut contoh sederhana
ResponseStatus rs = e32ttl.sendFixedMessage(0, 0, 0x17, &messaggione, sizeof(Messaggione));// ResponseStatus rs = e32ttl.sendFixedMessage(0, 0, 0x17, "Ciao");
Transmisi tetap memiliki lebih banyak skenario
Jika Anda mengirim ke perangkat tertentu (skenario kedua Transmisi tetap), Anda harus menambahkan ADDL, ADDH dan CHAN untuk mengidentifikasinya secara langsung.
ResponseStatus rs = e32ttl.sendFixedMessage(2, 2, 0x17, "Pesan ke perangkat");
Jika Anda ingin mengirim pesan ke semua perangkat di Saluran tertentu, Anda dapat menggunakan metode ini.
ResponseStatus rs = e32ttl.sendBroadcastFixedMessage(0x17, "Pesan ke perangkat saluran");
Jika Anda ingin menerima semua pesan broadcast di jaringan Anda harus mengatur ADDH dan ADDL Anda dengan BROADCAST_ADDRESS.
ResponseStructContainer c;c = e32ttl100.getConfiguration(); // Penting untuk mendapatkan pointer konfigurasi sebelum semua operasi lainnya Konfigurasi konfigurasi = *(Konfigurasi*) c.data; Serial.println(c.status.getResponseDescription()); Serial.println(c.status.code); printParameters(konfigurasi); konfigurasi. ADDL = BROADCAST_ADDRESS; konfigurasi. ADDH = BROADCAST_ADDRESS; // Atur konfigurasi yang diubah dan atur untuk tidak menahan konfigurasi ResponseStatus rs = e32ttl100.setConfiguration(configuration, WRITE_CFG_PWR_DWN_LOSE); Serial.println(rs.getResponseDescription()); Serial.println(rs.code); printParameters(konfigurasi);
Langkah 15: Terima kasih
Sekarang Anda memiliki semua informasi untuk melakukan pekerjaan Anda, tetapi saya pikir Penting untuk menunjukkan beberapa contoh realistis untuk lebih memahami semua kemungkinan.
- Perangkat LoRa E32 untuk Arduino, esp32 atau esp8266: pengaturan dan penggunaan dasar
- Perangkat LoRa E32 untuk Arduino, esp32 atau esp8266: perpustakaan
- Perangkat LoRa E32 untuk Arduino, esp32 atau esp8266: konfigurasi
- Perangkat LoRa E32 untuk Arduino, esp32 atau esp8266: transmisi tetap
- Perangkat LoRa E32 untuk Arduino, esp32 atau esp8266: hemat daya dan mengirim data terstruktur
Direkomendasikan:
Cara Membuat Perangkat EKG Berbiaya Rendah: 26 Langkah
Cara Membuat Perangkat EKG Berbiaya Rendah: Halo semuanya! Nama saya Mariano dan saya seorang insinyur biomedis. Saya menghabiskan beberapa akhir pekan untuk merancang dan mewujudkan prototipe perangkat EKG berbiaya rendah berbasis papan Arduino yang terhubung melalui Bluetooth ke perangkat Android (smartphone atau tablet). Saya akan
LoRa Remote Control Messenger Dengan TFT 1,8" untuk Jarak Hingga 8km: 8 Langkah
LoRa Remote Control Messenger Dengan TFT 1,8" untuk Jarak Hingga 8km: Hubungkan proyek ke laptop atau ponsel Anda dan kemudian mengobrol antar perangkat tanpa internet atau SMS hanya menggunakan LoRa.Hai, apa kabar guys? Akarsh di sini dari CETech.Ini PCB juga memiliki tampilan dan 4 tombol yang dapat digunakan sebagai remote control untuk
Jarak Jauh, 1,8km, Komunikasi Nirkabel Arduino ke Arduino Dengan HC-12.: 6 Langkah (dengan Gambar)
Jarak Jauh, 1,8km, Komunikasi Nirkabel Arduino ke Arduino Dengan HC-12.: Dalam instruksi ini Anda akan belajar bagaimana berkomunikasi antara Arduino melalui jarak jauh hingga 1,8km di udara terbuka. HC-12 adalah port serial nirkabel modul komunikasi yang sangat berguna, sangat kuat dan mudah digunakan. Pertama Anda akan meninggalkan
Jaringan Sensor Nirkabel Berbiaya Rendah pada Pita 433MHz: 5 Langkah (dengan Gambar)
Jaringan Sensor Nirkabel Berbiaya Rendah pada Pita 433MHz: Terima kasih banyak kepada Teresa Rajba karena telah memberi saya persetujuannya untuk menggunakan data dari publikasi mereka di artikel ini.*Pada gambar di atas - lima unit pengirim sensor yang saya gunakan untuk pengujianApa itu sensor nirkabel jaringan? Definisi sederhana akan
LoRa Messenger untuk Dua Perangkat untuk Jarak Hingga 8km: 7 Langkah
LoRa Messenger untuk Dua Perangkat untuk Jarak Hingga 8km: Hubungkan proyek ke laptop atau ponsel Anda dan kemudian mengobrol antar perangkat tanpa internet atau SMS hanya menggunakan LoRa.Hei, apa kabar guys? Akarsh di sini dari CETech. Hari ini kita akan membuat proyek yang dapat dihubungkan ke ponsel cerdas Anda atau