Kali ini saya berpikir untuk menyembunyikan pelacak GPS di sepeda saya sebagai tindakan pencegahan. Ada banyak perangkat otonom di pasar untuk melacak mobil, kargo, sepeda, koper, anak-anak dan hewan. Sebagian besar dari mereka berinteraksi dengan pengguna melalui SMS. Opsi yang lebih mahal menyediakan fitur Find my phone, tetapi terkait dengan layanan online tertentu.
Idealnya, saya ingin memiliki kontrol penuh atas pelacak: menggunakannya dalam mode yang nyaman tanpa SMS dan pendaftaran. Google dangkal membawakan saya beberapa modul dari China, salah satunya saya pesan (papan puding A9G) (~ $ 15).

Artikel ini adalah tentang bagaimana saya membuat python bekerja pada modul ini.
Jika A9G adalah analog ESP (pabrikan, omong-omong, sama), maka papan puding itu sendiri adalah analog dari papan NodeMCU, kecuali bahwa papan puding tidak memiliki konverter USB-UART bawaan. Tetapi ada banyak hal menarik lainnya. Spesifikasi produsen :
- 32 bit core (RISC), hingga 312MHz
- 29x GPIO (semua disolder, semua antarmuka termasuk dalam nomor ini)
- jam tangan dan anjing penjaga
- Antarmuka USB 1.1 1x (saya tidak menemukannya di sana, tetapi menyalin dari luar kantor) dan microUSB untuk daya
- 2x UART (layanan +1)
- 2x SPI (belum dicoba)
- 3x I2C (belum dicoba)
- 1x SDMMC (dengan slot fisik)
- 2x input analog (10 bit, mungkin salah satunya digunakan oleh pengontrol baterai lithium)
- 4 MB flash
- 4Mb PSRAM
- ADC (mikrofon, secara fisik ada di papan) dan DAC (speaker, absen)
- pengontrol pengisian daya baterai (tidak ada baterai sendiri)
- Bahkan, GSM (800, 900, 1800, 1900 MHz) dengan SMS, suara dan GPRS
- GPS terhubung melalui UART2 (ada modul "A9" tanpa itu)
- Slot SIM (nanoSIM)
- dua tombol (satu reset, yang lain - fungsi inklusi dan diprogram)
- dua LED
Tegangan operasi adalah 3.3V, tegangan input 5-3.8V (tergantung pada koneksi). Secara umum, modul memiliki semua perangkat keras yang diperlukan untuk merakitnya dari perangkat mobile tombol sederhana. Tetapi dari contoh-contoh itu tampaknya orang Cina membelinya untuk dijual dari mesin slot atau mesin slot atau sesuatu seperti itu. Alternatif untuk modul adalah modul SIM800 yang agak populer, yang, sayangnya, tidak memiliki SDK di domain publik (mis. Modul tersebut dijual sebagai modem AT).
SDK
Modul ini dilengkapi dengan SDK dalam bahasa Inggris yang memuaskan. Pemasangan di bawah Ubuntu, tetapi Windows dan kontainer lebih disukai. Semuanya berfungsi melalui poking di GUI: ESPtool untuk modul ini belum dikembalikan. Firmware itu sendiri dibangun oleh Makefile. Debugger hadir: sebelum pembekuan, modul melempar jejak stack ke port layanan. Tetapi secara pribadi, saya tidak bisa menerjemahkan alamat menjadi baris kode (gdb melaporkan bahwa alamat tidak sesuai dengan apa pun). Ada kemungkinan bahwa ini karena dukungan yang buruk untuk Linux. Dengan demikian, jika Anda ingin mengotak-atik modul - coba lakukan di Windows (dan berhenti berlangganan di github). Kalau tidak, inilah instruksi untuk Linux. Setelah instalasi, Anda perlu memeriksa kebenaran jalur di .bashrc dan menghapus (mengganti nama) semua file CSDTK/lib/libQt*
: jika tidak, flasher (alias debugger) tidak akan mulai karena konflik dengan, mungkin, libQt yang diinstal.

Untuk flasher ada instruksi .
Koneksi
Semuanya lebih rumit daripada di NodeMCU. Modul terlihat mirip, tetapi tidak ada chip USB-TTY pada papan puding dan microUSB hanya digunakan untuk daya. Karenanya, Anda akan membutuhkan USB-TTY di 3.3V. Dua lebih baik: satu untuk port debug dan satu untuk UART1: yang pertama digunakan untuk mengunggah firmware dan yang kedua dapat Anda gunakan sebagai terminal reguler. Agar tidak menyeret semua ingus ini ke komputer, saya juga membeli splitter USB 4-port dengan kabel dua meter dan catu daya eksternal (diperlukan). Total biaya kit ini dengan modul itu sendiri adalah $ 25-30 (tanpa catu daya: gunakan dari telepon).
Firmware
Modul ini dilengkapi dengan AT firmware: Anda dapat terhubung ke Arduino 3.3V dan menggunakannya sebagai modem melalui UART1. Firmware mereka ditulis dalam C. make
membuat dua file firmware: satu dijahit sekitar satu menit, yang lain cukup cepat. Hanya satu dari file ini yang dapat dijahit: pertama kali besar, kali berikutnya kecil. Secara total, selama proses pengembangan, saya memiliki SDK Cina ( coolwatcher
) terbuka di desktop untuk mengelola modul, miniterm sebagai stdio dan editor kode.
API
Konten API mencerminkan daftar di atas dan menyerupai ESP8266 pada hari-hari awalnya: saya butuh sekitar 3 jam untuk meluncurkan HelloWorld. Sayangnya, rangkaian fungsi yang tersedia bagi pengguna sangat terbatas: misalnya, tidak ada akses ke buku telepon pada kartu SIM, informasi tingkat rendah tentang menghubungkan ke jaringan seluler, dan sebagainya. Dokumentasi API bahkan kurang lengkap, jadi Anda harus bergantung pada contoh (yang ada dua lusin) dan memasukkan file. Namun demikian, modul ini dapat melakukan banyak hal hingga koneksi SSL: jelas, pabrikan fokus pada fungsi yang paling prioritas.
Namun, pemrograman mikrokontroler Cina melalui API Cina harus dicintai. Untuk semua orang, pabrikan mulai memasukkan port micropython ke modul ini. Saya memutuskan untuk mencoba sendiri dalam proyek open-source dan melanjutkan kerja bagus ini (tautan di akhir artikel).
micropython

Micropython adalah proyek open-source porting cPython ke mikrokontroler. Pengembangan dilakukan dalam dua arah. Yang pertama adalah dukungan dan pengembangan perpustakaan inti yang umum untuk semua mikrokontroler yang mendeskripsikan bekerja dengan tipe data utama dalam python: objek, fungsi, kelas, string, tipe atom, dan banyak lagi. Yang kedua adalah, pada kenyataannya, port: untuk setiap mikrokontroler perlu untuk "mengajar" perpustakaan untuk bekerja dengan UART untuk input-output, pilih tumpukan untuk mesin virtual, tentukan satu set optimisasi. Secara opsional, bekerja dengan perangkat keras dijelaskan: GPIO, daya, nirkabel, sistem file.
Semua ini ditulis dalam C murni dengan makro: micropython memiliki satu set resep yang direkomendasikan dari mendeklarasikan string dalam ROM ke modul penulisan. Selain itu, modul yang ditulis sendiri python didukung penuh (yang utama adalah jangan lupa tentang ukuran memori). Para kurator proyek menetapkan sebagai kesempatan mereka untuk meluncurkan dzhanga (gambar dengan sepotong roti). Sebagai iklan: proyek ini menjual papannya sendiri untuk siswa papan luncur , tetapi port untuk modul ESP8266 dan ESP32 juga populer.
Ketika firmware siap dan diunggah - Anda cukup menyambungkan ke mikrokontroler melalui UART dan masuk ke Python REPL.
$ miniterm.py /dev/ttyUSB1 115200 --raw MicroPython cd2f742 on 2017-11-29; unicorn with Cortex-M3 Type "help()" for more information. >>> print("hello") hello
Setelah itu, Anda dapat mulai menulis di python3 yang hampir normal tanpa melupakan keterbatasan memori.
Modul A9G tidak didukung secara resmi (daftar modul yang didukung secara resmi tersedia dalam micropython/ports
, ada sekitar selusin dari mereka). Namun demikian, pembuat besi itu bercabang micropython dan menciptakan lingkungan untuk port micropython/ports/gprs_a9
: micropython/ports/gprs_a9
, yang banyak terima kasih kepadanya. Pada saat saya tertarik dengan masalah ini, port berhasil dikompilasi dan mikrokontroler menyambut saya dengan REPL. Tapi, sayangnya, dari modul pihak ketiga hanya ada yang berfungsi dengan sistem file dan GPIO: tidak ada yang terkait dengan jaringan nirkabel dan GPS tersedia. Saya memutuskan untuk memperbaiki cacat ini dan menetapkan sendiri tujuan porting semua fungsi yang diperlukan untuk pelacak GPS. Dokumentasi resmi untuk kasus ini tidak perlu singkat: oleh karena itu, saya harus melihat-lihat kode.
Mulai dari mana
Pertama, pergi ke micropython/ports
dan salin micropython/ports/minimal
ke folder baru di mana port akan berada. Kemudian, edit main.c
untuk platform Anda. Perlu diingat bahwa semua yummy berada di fungsi main
, di mana Anda perlu memanggil mp_init()
, setelah sebelumnya menyiapkan mikrokontroler dan menumpuk pengaturan untuk itu. Kemudian, untuk API yang digerakkan oleh peristiwa, Anda perlu memanggil pyexec_event_repl_init()
dan memberi makan karakter yang dimasukkan melalui UART ke fungsi pyexec_event_repl_process_char(char)
. Ini akan memberikan interoperabilitas melalui REPL. File kedua, micropython/ports/minimal/uart_core.c
menjelaskan pemblokiran input dan output di UART. Saya membawa kode asli untuk STM32 bagi mereka yang terlalu malas untuk mencari.
main.c
int main(int argc, char **argv) { int stack_dummy; stack_top = (char*)&stack_dummy; #if MICROPY_ENABLE_GC gc_init(heap, heap + sizeof(heap)); #endif mp_init(); #if MICROPY_ENABLE_COMPILER #if MICROPY_REPL_EVENT_DRIVEN pyexec_event_repl_init(); for (;;) { int c = mp_hal_stdin_rx_chr(); if (pyexec_event_repl_process_char(c)) { break; } } #else pyexec_friendly_repl(); #endif
uart_core.c
Setelah itu, Anda perlu menulis ulang Makefile menggunakan rekomendasi / kompiler dari pabrikan: semuanya individual di sini. Semuanya, ini idealnya sudah cukup: kami mengumpulkan, mengisi firmware dan melihat REPL di UART.
Setelah menghidupkan kembali micropython
Anda perlu menjaga kesejahteraannya: mengatur pengumpul sampah, reaksi yang benar terhadap Ctrl-D (soft reset) dan beberapa hal lain yang tidak akan saya mpconfigport.h
: lihat file mpconfigport.h
.
Buat modul
Yang paling menarik adalah menulis modul Anda sendiri. Jadi, modul (tidak perlu, tetapi diinginkan) dimulai dengan file mod[].c
, yang ditambahkan oleh Makefile
(variabel SRC_C
jika Anda mengikuti konvensi). Modul kosong adalah sebagai berikut:
Tentu saja, port itu sendiri tidak mengenali konstanta mp_module_mymodule
: ia harus ditambahkan ke variabel MICROPY_PORT_BUILTIN_MODULES
dalam pengaturan port mpconfigport.h
. Ngomong-ngomong wallpaper membosankan nama chip dan nama port juga berubah di sana. Setelah semua perubahan ini, Anda dapat mencoba mengkompilasi modul dan mengimpornya dari REPL. Hanya satu atribut __name__
dengan nama modul yang akan tersedia untuk modul (kasus yang bagus untuk memeriksa pelengkapan otomatis di REPL via Tab).
>>> import mymodule >>> mymodule.__name__ 'mymodule'
Konstanta
Tahap selanjutnya dalam kompleksitas adalah menambahkan konstanta. Konstanta sering diperlukan untuk pengaturan ( INPUT
, OUTPUT
, HIGH
, LOW
, dll.) Semuanya cukup sederhana di sini. Di sini, sebagai contoh, konstanta magic_number = 10
:
STATIC const mp_map_elem_t mymodule_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_mymodule) }, { MP_OBJ_NEW_QSTR(MP_QSTR_magic_number), MP_OBJ_NEW_SMALL_INT(10) }, };
Pengujian:
>>> import mymodule >>> mymodule.magic_number 10
Fungsi
Menambahkan fungsi ke modul mengikuti prinsip umum: menyatakan, membungkus, menambah (Saya memberikan contoh yang sedikit lebih kompleks daripada di dokumentasi).
Tes:
>>> import mymodule >>> mymodule.conditional_add_one(3) 4 >>> mymodule.conditional_add_one(9) >>>
Kelas (Jenis)
Dengan kelas (tipe), semuanya juga relatif sederhana. Berikut ini adalah contoh dari dokumentasi (well, hampir):
Tes:
>>> mymodule.helloObj <type 'helloObj'>
Jenis yang dihasilkan dapat diwariskan, dibandingkan, tetapi tidak memiliki konstruktor atau data terkait. Data ditambahkan "di sebelah" konstruktor: diusulkan untuk membuat struktur terpisah di mana tipe Python akan disimpan secara terpisah dan terpisah - satu set data sewenang-wenang.
Bagaimana cara berinteraksi dengan data ini? Salah satu cara tersulit adalah melalui konstruktor.
Dari bidang lain, ada juga .print
, dan saya kira sisa sihir Python3
.
Tetapi make_new
tidak diperlukan sama sekali untuk mendapatkan instance dari suatu objek: inisialisasi dapat dilakukan dalam fungsi arbitrer. Berikut ini adalah contoh yang bagus dari micropython/ports/esp32/modsocket.c
:
Metode terikat
Langkah selanjutnya adalah menambahkan metode terikat. Namun, ini tidak jauh berbeda dari semua metode lain. Kami kembali ke contoh dari dokumentasi:
Itu saja!
>>> x = mymodule.helloObj(12) >>> x.inc()
Semua atribut lainnya: getattr , setattr
Bagaimana dengan menambahkan non-fungsi, menggunakan @property
dan umumnya __getattr__
Anda sendiri? Tolong: ini dilakukan secara manual melewati mymodule_hello_locals_dict_table
.
Ternyata sesuatu yang singkat dan menyakitkan, katamu. Di mana semua mp_raise_AttributeError
ini ( catatan : fungsi seperti itu tidak ada)? Bahkan, sebuah AttributeError
akan dipanggil secara otomatis. Rahasianya adalah bahwa dest
adalah array dari dua elemen. Elemen pertama memiliki arti "output", hanya menulis: dibutuhkan nilai MP_OBJ_SENTINEL
jika nilainya perlu ditulis dan MP_OBJ_NULL
jika perlu dibaca. Dengan demikian, pada saat keluar dari fungsi, MP_OBJ_NULL
diharapkan dalam kasus pertama dan sesuatu mp_obj_t
di yang kedua. Elemen kedua adalah input, hanya-baca: mengambil nilai objek untuk ditulis jika nilainya perlu ditulis dan MP_OBJ_NULL
jika perlu dibaca. Anda tidak perlu mengubahnya.
Itu saja, Anda dapat memeriksa:
>>> x = mymodule.helloObj(12) >>> x.val = 3 >>> x.val 3
Yang paling menarik adalah bahwa penyelesaian Tab di REPL masih berfungsi dan menawarkan .val
! Sejujurnya, saya bukan ahli C, jadi saya hanya bisa menebak bagaimana ini terjadi (dengan mendefinisikan ulang operator '==').
Pelabuhan
Kembali ke modul A9G, saya menggambarkan dukungan semua fungsi dasar, yaitu, SMS, GPRS (soket), GPS, manajemen daya. Sekarang Anda dapat mengunggah sesuatu seperti ini ke modul dan itu akan berfungsi:
import cellular as c import usocket as sock import time import gps import machine
Proyek menerima bantuan yang layak. Jika Anda menyukai proyek dan / atau artikel ini, jangan lupa untuk meninggalkan like di github .