Optimalisasi Energi STM32: Panduan Praktis

Halo, Habr!

Ada banyak artikel di jaringan tentang pengoperasian mikrokontroler STM32 dalam perangkat hemat energi - biasanya perangkat bertenaga baterai - namun, di antara mereka sangat disayangkan bahwa mereka tidak memahami topik ini di luar daftar mode hemat energi dan perintah SPL / HAL yang memasukkannya (namun, klaim yang sama berlaku) untuk sebagian besar artikel tentang bekerja dengan STM32).

Sementara itu, karena pesatnya perkembangan rumah pintar dan semua jenis IoT, topik ini menjadi semakin relevan - dalam sistem seperti itu, banyak komponen bertenaga baterai, dan bertahun-tahun operasi berkelanjutan diharapkan dari mereka.

Kami akan mengisi celah ini dengan contoh STM32L1 - pengontrol yang sangat populer, cukup ekonomis dan pada saat yang sama memiliki beberapa masalah khusus untuk seri ini. Hampir semua hal di atas juga akan berlaku untuk STM32L0 dan STM32L4, dan dalam hal masalah dan pendekatan umum, untuk pengontrol lain berdasarkan inti Cortex-M.



Hasil praktisnya akan terlihat seperti foto di atas (dan ya, kami juga akan berbicara tentang penerapan multimeter dan alat ukur lainnya untuk tugas serupa).

Mode Penghemat Daya di STM32L1


Dasar-dasar penghematan baterai adalah mode hemat daya utama prosesor. Masing-masing pabrikan dan setiap rangkaian pengontrol memiliki sendiri (satu set spesifik adalah perpanjangan vendor dari mode inti Cortex-M standar dengan berbagai nuansa mengenai periferal, voltase pasokan, dll.).

Secara khusus, STM32L1, yang termasuk dalam rangkaian pengontrol ekonomis, dan sehubungan dengan ini, antara lain, menerima rangkaian pengaturan daya yang diperluas, kami memiliki yang berikut ini:

  • Jalankan - mode normal. Semua inklusif, semua periferal tersedia, frekuensi hingga 32 MHz.
  • Low Power Run (LP Run) - mode khusus dengan frekuensi operasi dalam 131 kHz dan konsumsi maksimum, dengan mempertimbangkan seluruh periferal , 200 μA. Dalam mode LP Run, regulator daya prosesor beralih ke mode ekonomis khusus, yang menghemat hingga lima puluh mikroamp dibandingkan dengan bekerja pada frekuensi yang sama dalam mode Run.
  • Tidur - penangguhan kernel, tetapi dengan pelestarian semua frekuensi clock. Periferal prosesor dapat terus berfungsi jika kernel tidak membutuhkannya, tetapi dapat dimatikan secara otomatis.
  • Low Power Sleep (LP Sleep) - kombinasi dari Sleep dengan transisi dari stabilizer ke mode ekonomis. Frekuensi clock tidak lebih tinggi dari 131 kHz, total konsumsi tidak lebih tinggi dari 200 μA.
  • Stop - penghentian total semua frekuensi clock, kecuali untuk generator "clock" 32768 Hz, eksternal atau internal. Dalam kasus STM32L1, hanya jam waktu-nyata yang terus bekerja dalam mode ini, yang lainnya berhenti sepenuhnya; pada prosesor yang lebih baru, beberapa periferal dapat clock pada frekuensi rendah. Hampir semua kaki prosesor mempertahankan statusnya. Isi RAM disimpan, interupsi eksternal terus bekerja.
  • Standby - penonaktifan inti prosesor, RAM, dan semua periferal lengkap, kecuali untuk jam waktu-nyata. RAM tidak disimpan (mis., Dari sudut pandang perangkat lunak, meninggalkan Standby hampir sama dengan mendistorsi catu daya - mulai dari awal), RTC terus mencentang. Interupsi eksternal tidak berfungsi, kecuali untuk tiga kaki WKUPx khusus, yang beralih dari 0 ke 1 membangunkan prosesor.

Memasuki masing-masing mode cukup sederhana - Anda perlu mengatur bendera dalam tiga hingga lima register, setelah itu (untuk mode tidur) memanggil instruksi WFI atau WFE, ini adalah instruksi standar Cortex-M, berarti "Tunggu Gangguan" dan "Tunggu Acara" . Bergantung pada flag-flag (mereka dijelaskan dalam Manual Referensi prosesor, untuk STM32L1 adalah RM0038 ), prosesor itu sendiri akan masuk ke mode ini pada perintah ini.

Selain itu, akan lebih baik untuk melarang interupsi (ini tidak akan mempengaruhi kemampuan peristiwa eksternal dan internal untuk membangunkan prosesor dari tidur) dan menunggu data disimpan dari register ke memori jika tiba-tiba terjadi, menggunakan perintah DSB.

Sebagai contoh, ini adalah bagaimana masuk ke mode Stop terlihat seperti:

/*  PDDS    Stop  Standby,    */ PWR->CR &= ~(PWR_CR_PDDS); /*  Wakeup   ,      */ PWR->CR |= PWR_CR_CWUF; /*    low-power ,    Stop -    */ PWR->CR |= PWR_CR_LPSDSR; /*    Vref   */ PWR->CR |= PWR_CR_ULP; /*     Cortex-M,  Stop,  Standby -   Deep Sleep */ /*      Deep Sleep */ SCB->SCR |= (SCB_SCR_SLEEPDEEP_Msk); /*  ;       */ unsigned state = irq_disable(); /*      */ __DSB(); /*  */ __WFI(); /*    */ init_clk(); /*     */ irq_restore(state); 

WFI adalah instruksi pemblokiran, di atasnya prosesor akan tertidur nyenyak dan tidak akan keluar sampai terjadi gangguan. Ya, saya ulangi, terlepas dari kenyataan bahwa kami secara eksplisit mematikan interupsi, prosesor akan merespons dan bangun - tetapi hanya akan mulai memproses setelah kami menyalakannya kembali. Dan ini memiliki makna yang dalam.

Dalam kode di atas, setelah WFI, beberapa jenis reinisialisasi frekuensi operasi berjalan tidak begitu saja - faktanya adalah L1 selalu meninggalkan tidur nyenyak pada frekuensi 4,2 MHz dan dengan generator MSI internal sebagai sumber frekuensi ini. Dalam banyak situasi, Anda jelas tidak ingin interrupt handler yang membangunkan prosesor untuk mulai berjalan pada frekuensi ini - misalnya, karena frekuensi semua timer, UART, dan bus lain akan terbang; oleh karena itu, pertama-tama kita mengembalikan frekuensi operasi (atau, jika kita ingin tetap menggunakan MSI, menghitung ulang bus-bus yang diperlukan di bawah 4,2 MHz), dan kemudian kita menyelami interupsi.

Dalam praktiknya, dua mode yang paling sering digunakan adalah Run and Stop. Faktanya adalah bahwa LP Run sangat lambat dan tidak masuk akal jika prosesor perlu melakukan beberapa perhitungan dan tidak hanya menunggu peristiwa eksternal, dan Sleep dan LP Sleep tidak terlalu ekonomis (konsumsi hingga 2 mA) dan diperlukan jika Anda perlu menghemat setidaknya sedikit, tetapi pada saat yang sama meninggalkan peripheral yang berfungsi dan / atau memberikan reaksi prosesor secepat mungkin terhadap berbagai peristiwa. Persyaratan seperti itu memang ada, tetapi secara keseluruhan tidak terlalu sering.

Mode siaga biasanya tidak digunakan, karena setelah itu tidak mungkin untuk melanjutkan dari tempat Anda tinggalkan karena zeroing RAM, ada juga beberapa masalah dengan perangkat eksternal, yang akan kita bahas di bawah ini, yang memerlukan solusi perangkat keras. Namun, jika perangkat dirancang dengan mempertimbangkan hal ini, Siaga dapat digunakan sebagai mode "mati", misalnya, selama penyimpanan jangka panjang perangkat ini.

Sebenarnya, pada presentasi ini, sebagian besar manual biasanya mati dengan kemenangan.

Masalahnya adalah, mengikuti mereka, Anda akan mendapatkan 100-200 μA konsumsi riil yang menyedihkan alih-alih yang dijanjikan 1,4 μA dalam Stop dengan jam kerja - bahkan pada debugging referensi Nucleo, yang tidak memiliki chip eksternal, sensor, dll. yang dapat dikaitkan.

Dan tidak, prosesor Anda berfungsi, tidak ada yang salah, dan Anda melakukan semuanya dengan benar.

Hanya tidak sampai akhir.

Sindrom kaki gelisah


Masalah pertama STM32L1, tentang mana beberapa artikel menyebutkan, tetapi sering hanya ingat di forum, ketika pada hari ketiga diskusi, dari mana datangnya 100-200 μA, seseorang mengingat keberadaan AN3430 dan mencapai halaman 19 di dalamnya - ini status kaki secara default.

Saya perhatikan bahwa bahkan STMicro sendiri merujuk pada masalah melalui selongsong, dan dalam sebagian besar dokumen di mana optimasi konsumsi energi dipertimbangkan, itu terbatas pada satu atau dua frasa dengan saran untuk menarik kaki yang tidak digunakan ke tanah atau dimasukkan ke mode input analog, tanpa menjelaskan alasannya.

Yang menyedihkan adalah bahwa secara default, semua kaki dikonfigurasi sebagai input digital (0x00 dalam register GPIOx_MODER). Pemicu Schmitt selalu pada input digital, yang meningkatkan imunitas noise dari input ini, dan sepenuhnya independen - ini adalah elemen logika sederhana, buffer dengan histeresis yang tidak memerlukan pencatatan jam kerja eksternal.

Dalam kasus kami, ini berarti bahwa kami mematikan jam dalam mode Stop, dan pemicu Schmitt terus bekerja seolah-olah tidak ada yang terjadi - tergantung pada tingkat sinyal input, mereka mengalihkan output ke 0 dan 1.

Pada saat yang sama, bagian dari kaki prosesor di sirkuit tipikal menggantung di udara - yaitu, tidak ada sinyal yang dapat dipahami pada mereka. Adalah keliru untuk berpikir bahwa tidak adanya sinyal yang jelas berarti bahwa pada kaki-kaki ini 0 tidak, pada kaki-kaki ini karena impedansi masukannya yang tinggi, ada beberapa suara acak dari nilai yang tidak ditentukan, dari pickup dan arus yang mengalir dari trek tetangga ke saluran pertama televisi, jika kaki cukup panjang untuk berfungsi sebagai antena (namun, TV analog di Rusia akan segera dimatikan, yang akan mengarah pada beberapa pengurangan konsumsi daya mikrokontroler yang dikonfigurasi secara salah).

Sesuai dengan fluktuasi ini, kaki dalam beberapa cara acak beralih antara 0 dan 1. Logika CMOS mengkonsumsi arus saat beralih. Yaitu, kaki prosesor yang menggantung di udara, dikonfigurasi dalam mode input digital, mengkonsumsi arus yang terlihat dengan sendirinya .

Jalan keluarnya sederhana - saat Anda memulai program, Anda perlu mengonfigurasi semua kaki ke keadaan input analog; STM32 memilikinya secara formal untuk semua kaki tanpa kecuali, terlepas dari apakah mereka terhubung ke ADC atau tidak, dan berbeda dari input digital hanya dengan tidak adanya pemicu Schmitt pada input.



Untuk melakukan ini, cukup menuliskan nilai 0xFF ... FF ke semua register GPIOx_MODER, paling mudah untuk melakukan ini, seperti yang disebutkan di atas, tepat di awal, dan kemudian selama permainan, Anda akan mengonfigurasi ulang setiap kaki sesuai kebutuhan pada perangkat ini.

Namun, di sini muncul masalah tingkat kedua - ada baiknya jika firmware Anda bekerja pada satu pengontrol tertentu, dan karena itu Anda selalu tahu apa yang ada di GPIOx. Lebih buruk jika firmware bersifat universal - STM32 dapat memiliki hingga 8 port, tetapi bisa lebih kecil; ketika Anda mencoba menulis ke port yang tidak ada dalam model controller ini, Anda akan mendapatkan Hard Fault, mis. kernel crash.

Namun, bahkan kasus ini dapat dielakkan - Cortex-M memungkinkan Anda memeriksa alamat untuk validitasnya, apalagi, dalam kasus M3 dan M4, pemeriksaan umumnya sepele, dan pada M0 itu memerlukan beberapa keajaiban, tetapi ini dapat diwujudkan ( detail dapat dibaca di sini , kami tidak akan menulis artikel ini) )

Artinya, secara umum, prosesor memulai, menyetel frekuensi - dan segera pergi melalui semua port GPIO yang tersedia, menuliskannya ke MODER (kode di bawah ini ditulis untuk RIOT OS, tetapi secara umum jelas tanpa komentar dan dapat ditransfer ke tiga menit platform lain).

 #if defined(CPU_FAM_STM32L1) /* switch all GPIOs to AIN mode to minimize power consumption */ GPIO_TypeDef *port; /* enable GPIO clock */ uint32_t ahb_gpio_clocks = RCC->AHBENR & 0xFF; periph_clk_en(AHB, 0xFF); for (uint8_t i = 0; i < 8; i++) { port = (GPIO_TypeDef *)(GPIOA_BASE + i*(GPIOB_BASE - GPIOA_BASE)); if (cpu_check_address((char *)port)) { port->MODER = 0xffffffff; } else { break; } } /* restore GPIO clock */ uint32_t tmpreg = RCC->AHBENR; tmpreg &= ~((uint32_t)0xFF); tmpreg |= ahb_gpio_clocks; periph_clk_en(AHB, tmpreg); #endif 

Saya perhatikan bahwa ini hanya berlaku untuk seri L1, di L0 dan L4 pengalaman diperhitungkan, dan mereka, secara default, mengkonfigurasi semua port sebagai input analog saat startup.

Setelah dengan hati-hati melakukan semua prosedur ini, Anda mengisi firmware ke perangkat yang sudah selesai ... dan mendapatkan 150 uA dalam mode Stop pada prosesor dan semua chip eksternal dimatikan, terlepas dari kenyataan bahwa perkiraan Anda adalah yang paling pesimistis, datang dari lembar data untuk semua yang telah disolder di papan tulis berikan tidak lebih tinggi dari 10 μA.

Selain itu, Anda mencoba untuk membawa prosesor ke Siaga alih-alih Berhenti, mis. matikan saja hampir sepenuhnya - dan bukannya jatuh, konsumsi daya meningkat tiga kali lipat, mendekati hampir setengah miliampere!

Tidak perlu panik. Seperti yang Anda duga, Anda melakukan segalanya dengan benar. Tetapi tidak sampai akhir.

Sindrom Kaki Gelisah - 2


Masalah selanjutnya memiliki dua bagian.

Yang pertama cukup jelas: jika perangkat Anda tidak terdiri dari satu mikrokontroler, maka penting untuk tidak lupa bahwa chip eksternal juga memiliki sinyal input yang memicu Schmitt menggantung, dan yang, lebih lanjut, dapat membangkitkan logika internal chip. Misalnya, sebuah chip yang ditarik dan dikeluarkan dari tidurnya oleh tim UART akan mencoba membaca data darinya dengan gerakan apa pun di bus ini.

Karenanya, jika semua kaki ini digantung di udara, kami tidak akan mendapatkan apa pun yang baik.

Dalam kondisi apa mereka berakhir di udara?

Pertama, ketika controller masuk ke mode Standby, semua GPIO ditransfer ke kondisi High-Z, dengan resistansi tinggi - yaitu, sebenarnya, chip eksternal yang terhubung dengannya ada di udara. Tidak mungkin untuk memperbaikinya secara terprogram dalam STM32L1 (dalam seri lain dan pengontrol lain hal itu terjadi dengan cara yang berbeda), oleh karena itu satu-satunya jalan keluar - dalam sistem yang menggunakan mode Siaga, input chip eksternal harus ditarik ke tanah atau ditenagai oleh resistor eksternal.

Tingkat tertentu dipilih sehingga garis tidak aktif dari sudut pandang chip:

  • 1 untuk UART TX
  • 0 untuk SPI MOSI
  • 0 untuk SPI CLK pada Mode SPI 0 atau 1
  • 1 untuk SPI CLK dengan Mode SPI 2 atau 3
  • 1 untuk SPI CS

Kedua, pada STM32 saat menggunakan Stop (sic!) Mode, keadaan GPIO yang terhubung ke blok perangkat keras internal antarmuka dapat ... berbeda. Yaitu, antarmuka SPI yang sama, ketika dikonfigurasi, dalam Stop tiba-tiba berubah menjadi input digital, atau, secara umum, High-Z - dengan konsekuensi yang sesuai untuk chip eksternal yang tergantung padanya. Walaupun dokumentasi menyatakan bahwa kaki dalam kondisi baik, Anda dapat mengandalkan apriori hanya jika Anda menggunakan kaki sebagai GPIO biasa.

Anda tidak dapat memahami dan memaafkannya, tetapi Anda dapat mengingat dan memperbaikinya: untuk antarmuka yang berperilaku seperti ini, Anda harus menambahkan pemindahan paksa ke GPIO normal dengan level yang sesuai dengan level tidak aktif dari antarmuka ini dalam fungsi perawatan tidur. Setelah bangun tidur, antarmuka dapat dipulihkan.

Sebagai contoh, SPI yang sama sebelum tidur (untuk kesederhanaan, saya mengambil kode dari RIOT OS, jelas bahwa hal yang sama mudah diterapkan pada register):

 /* specifically set GPIOs used for external SPI devices */ /* MOSI = 0, SCK = 0, MISO = AIN for SPI Mode 0 & 1 (CPOL = 0) */ /* MOSI = 0, SCK = 1, MISO = AIN for SPI Mode 2 & 3 (CPOL = 1) */ for (i = 0; i < SPI_NUMOF; i++) { /* check if SPI is in use */ if (is_periph_clk(spi_config[i].apbbus, spi_config[i].rccmask) == 1) { /* SPI CLK polarity */ if (spi_config[i].dev->CR1 & (1<<1)) { gpio_init(spi_config[i].sclk_pin, GPIO_IN_PU); } else { gpio_init(spi_config[i].sclk_pin, GPIO_IN_PD); } gpio_init(spi_config[i].mosi_pin, GPIO_IN_PD); gpio_init(spi_config[i].miso_pin, GPIO_AIN); } } 

Harap dicatat bahwa output di sini dikonfigurasikan bukan sebagai GPIO_OUT dengan level 0 atau 1, tetapi sebagai input dengan pull-up hingga 0 atau 1 - ini bukan poin mendasar, tetapi memberikan keamanan tambahan jika Anda melakukan kesalahan dan mencoba untuk bermain push-push dengan beberapa jenis sebuah chip eksternal menarik kaki ini dengan cara lain. Dengan GPIO_OUT Anda dapat mengatur korsleting, dengan GPIO_IN dengan pull-up - tidak pernah.

Selain itu, sinyal CS SPI tidak terpengaruh - dalam hal ini, dihasilkan secara terprogram, yaitu, dengan GPIO normal, dan menjaga keadaannya dalam mimpi dengan penuh percaya diri.

Untuk mengembalikan keadaan kaki ketika meninggalkan tidur, cukup untuk menulis nilai register yang akan diubah (MODER, PUPDR, OTYPER, OSPEEDR - lihat situasi dalam kasus tertentu) di pintu masuk, ke dalam variabel, dan gulung kembali ke register ketika meninggalkan tidur dari variabel. .

Dan sekarang ... ta daam! Gambar judul. Satu setengah microamp.

Tapi terlalu dini untuk merayakannya. Pada ini kita telah menyelesaikan optimalisasi statis konsumsi energi, dan di depan kita adalah dinamis .

Achilles vs Turtle


Mana yang lebih baik - makan lebih banyak dan berlari lebih cepat atau makan lebih sedikit, tetapi jalankan lebih lambat? Dalam kasus mikrokontroler, jawaban atas pertanyaan ini adalah dua kali tidak trivial.

Pertama, frekuensi operasi dapat diubah dalam rentang yang sangat luas - dari 65 kHz (LP Run) ke 32 MHz dalam mode normal. Seperti halnya chip CMOS, STM32 memiliki dua komponen dalam konsumsi daya - statis dan dinamis; yang kedua tergantung pada frekuensi, yang pertama adalah konstan. Akibatnya, konsumsi energi tidak akan berkurang secepat frekuensi operasi dan produktivitas, dan tergantung pada tugasnya, frekuensi optimal dari sudut pandang efisiensi energi mungkin berubah menjadi berbeda - di mana Anda perlu menunggu beberapa peristiwa, tetapi karena alasan tertentu Anda tidak bisa tidur, akan ada frekuensi rendah efektif, di mana Anda hanya perlu mengirik angka - tinggi. Dalam tugas-tugas "rata-rata rumah sakit" yang khas, biasanya tidak masuk akal untuk pergi di bawah 2-4 MHz.

Kedua, dan ini adalah momen yang kurang sepele, tingkat tidur tergantung pada frekuensi kerja dan cara diterima.

Kasus terburuk adalah keluar dari tidur pada frekuensi 32 MHz dari kuarsa eksternal (izinkan saya mengingatkan Anda bahwa STM32L1 bangun pada osilator 4 MHz internal), karena terdiri dari tiga tahap:

  • sebenarnya prosesor bangun dari tidur
  • stabilisasi generasi kuarsa (1-24 MHz)
  • Stabilisasi generasi PLL (32 MHz)

Sebenarnya, mengeluarkan prosesor dari tidur di sini adalah masalah terkecil, pada frekuensi 4,2 MHz dibutuhkan sekitar 10 μs. Tetapi stabilisasi kuarsa dapat memakan waktu hingga 1 ms (meskipun biasanya untuk resonator kecepatan tinggi masih lebih cepat, pada urutan beberapa ratus mikrodetik), akses ke mode PLL adalah 160 μs.

Penundaan ini mungkin tidak signifikan dari sudut pandang konsumsi energi untuk sistem yang jarang bangun (tidak lebih dari sekali per detik), tetapi di mana periode antara bangun adalah puluhan milidetik dan kurang, dan bangun itu sendiri pendek, overhead mulai membuat penambahan yang sudah terukur bahkan dengan mempertimbangkan bahwa selama bangun prosesor mengkonsumsi arus yang relatif kecil.

Apa yang bisa dilakukan dengan ini? Secara umum, jawabannya jelas: cobalah untuk menghindari menggunakan kuarsa eksternal. Misalnya, sebuah program di mana ada subtugas berat yang langka yang membutuhkan pencatatan jam kerja yang akurat (misalnya, yang sepele - pertukaran data UART), dan subtugas sederhana yang sering, dapat memutuskan sendiri setiap kali pencerahan apakah perlu untuk pergi ke kuarsa eksternal, atau akan lebih mudah (dan lebih cepat!) untuk melakukan tugas saat ini pada generator MSI, di mana prosesor sudah bangun tanpa menghabiskan banyak waktu untuk menginisialisasi frekuensi.

Namun, dalam kasus ini, mungkin perlu menyesuaikan frekuensi jam periferal, serta menyesuaikan mode akses ke memori flash (jumlah siklus penundaan), tegangan inti prosesor (dalam STM32L1 dipilih dari tiga nilai yang mungkin), dll. Namun, berkenaan dengan mode operasi kernel dan memori, sering kali dimungkinkan untuk menyempurnakannya dengan memilih yang direkomendasikan untuk frekuensi maksimum yang digunakan, karena operasi inti yang tidak optimal pada frekuensi yang lebih rendah tidak akan memberikan perubahan signifikan dalam kinerja praktis dan konsumsi daya karena volume tugas yang kecil pada frekuensi ini. dilakukan.

Meskipun semua tindakan tersebut sudah diterapkan pada mode fine tuning (dan, misalnya, sebagian besar OS dan perpustakaan bahkan tidak tahu apa-apa dekat dengan kotak), dalam beberapa kasus mereka dapat menyebabkan penurunan konsumsi rata-rata pada skala unit persen, dan kadang-kadang bahkan lebih. Bayangkan, misalnya, meteran air yang mengotori kontak saklar buluh setiap 50 ms, sedangkan survei aktual membutuhkan beberapa puluh mikrodetik - apakah Anda ingin menambahkan ~ 500 μs saat ini untuk membangunkan pengontrol? ..

Detik yang tak tertahankan lama


Masalah lain yang tidak berkaitan langsung dengan konservasi energi, tetapi mau tidak mau muncul sehubungan dengan itu - bagaimana cara menghitung interval waktu kurang dari 1 detik?

Faktanya adalah bahwa pada STM32L1 hanya ada satu timer yang berfungsi dalam mode Stop - ini adalah RTC, satuan waktu standar yaitu 1 detik. Pada saat yang sama, dalam program selalu ada interval waktu unit, puluhan dan ratusan milidetik, untuk mengambil setidaknya meter air yang sama.

Bagaimana menjadi Jalankan prosesor dengan penghitung waktu LPTIM, dengan kecepatan 32768 Hz? Pilihan yang bagus, sebenarnya, tetapi tidak selalu perlu. Itu mungkin tanpa itu.

Tidak pada semua STM32L1, tetapi mulai dengan Cat. 2 (ini adalah prosesor STM32L151CB-A, STM32L151CC dan yang lebih baru), blok RTC dilengkapi dengan register baru - SSR, SubSeconds Register. Lebih tepatnya, itu tidak begitu banyak ditambah membuatnya terlihat oleh pengguna, ditambah ALRMASSR dan ALRMBSSR alarm ditambahkan.

Register ini tidak mengandung satuan waktu yang dapat dimengerti, itu dicambuk dari counter internal teknis. Dalam STM32L1, jam yang berdetak pada 32768 Hz melewati dua penghitung pembagi, asinkron dan sinkron, yang secara total biasanya membaginya dengan 32768 untuk mendapatkan centang 1 detik untuk jam tersebut. Jadi, SSR hanyalah nilai saat ini dari penghitung kedua.

Meskipun SSR tidak dihitung dalam milidetik, tetapi dalam unitnya, dimensi unit ini dapat diubah dengan mengubah rasio pembagi penghitung sinkron dan asinkron, sambil mempertahankan koefisien totalnya sebesar 32768 untuk mendapatkan standar 1 detik pada input RTC. Mengetahui koefisien-koefisien ini, kita dapat menghitung harga satu divisi SSR dalam milidetik, dan dari sini kita dapat melanjutkan ke pemrograman alarm sub-sekunder.

Perlu dicatat bahwa pre-counter asinkron lebih ekonomis daripada SSR sinkron, dan karenanya menetapkannya menjadi 1, dan sudah membagi frekuensi input ke dalam SSR sebesar 32768, setelah menerima hitungan hanya 30 μs, secara energetik tidak menguntungkan. Untuk kami sendiri, kami menentukan nilai optimal untuk pembagi awal 7, untuk sinkron - 4095 ((7 + 1) * (4095 + 1) = 32768). Dengan penurunan lebih lanjut dalam pembagi awal, konsumsi energi RTC mulai tumbuh secara terukur - oleh sebagian kecil dari microampere, tetapi karena kami membandingkannya dengan "referensi" 1,4 μA dalam mode Stop, bahkan fraksi penting. Secara default, untuk STM32L1 nilai-nilai ini adalah 127 dan 255, yaitu harga referensi sekitar 4 ms, yang agak kasar.

Jika Anda ingin menggali lebih dalam kode, maka pada waktunya kami menyelesaikan driver RTC standar dari RIOT OS untuk mendukung interval RTC_SSR dan milidetik. Sejak itu, kami telah menggunakannya secara harfiah di setiap langkah (dan karena kami bekerja di OS, sebuah layanan juga hang di atasnya, memungkinkan Anda untuk menggantung hampir semua tugas dengan periode acak pada satu pengatur waktu perangkat keras dengan satu jentikan pergelangan tangan).

Pendekatan yang sama ditransfer ke pengontrol STM32L0 dan STM32L4, semua model memiliki register RTC_SSR; ini menghilangkan kebutuhan untuk timer LPTIM dan menyatukan kode untuk platform yang berbeda.

Bagaimana memahami bahwa multimeter berbohong


Tentu saja, setelah semua optimasi, pertanyaan yang sah muncul: apa, sebenarnya, yang telah kita capai?Tanpa mengetahui jawabannya, seseorang dapat benar-benar membatasi dirinya pada satu WFE dengan flag yang terkonfigurasi dengan benar, tidur dan dapatkan 200-500 μA Anda.

Cara paling tradisional untuk mengukur arus adalah, tentu saja, multimeter. Untuk memahami bahwa ia berbaring di atas beban seperti mikrokontroler dengan konsumsi dinamisnya sangat sederhana - jika dihidupkan, ia berbohong.

Namun, ini tidak berarti bahwa multimeter tidak berguna dalam hal ini. Anda hanya perlu menerapkannya.

Pertama, multimeter adalah hal yang sangat lambat, waktu tipikal untuk satu hitungan di dalamnya adalah skala kedua, waktu tipikal untuk mengubah keadaan mikrokontroler adalah skala mikrodetik. Dalam sistem yang mengubah konsumsinya pada kecepatan itu, multimeter hanya akan menunjukkan nilai acak.

Namun, salah satu variabel nonrandom yang menarik minat kami adalah konsumsi mikrokontroler dalam mode tidur; jika secara signifikan melebihi nilai yang kami perkirakan pada lembar data, maka ada sesuatu yang jelas salah. Ini adalah konsumsi sistem statis , yaitu dapat diukur dengan multimeter.

Metode paling sepele yang ditunjukkan dalam foto judul adalah multimeter dalam mode microammeter, yang sekarang ada di sebagian besar model kelas menengah, dan memiliki akurasi yang baik dan resolusi yang sangat baik. UT120C memiliki resolusi 0,1 μA dengan akurasi bersertifikat dari ± 1% ± 3 debit, yang cukup bagi kami.

Hanya ada satu masalah dengan mode ini - multimeter di dalamnya memiliki resistansi seri besar, skala ratusan ohm, jadi dalam mode normal, mikrokontroler dengan multimeter dalam rangkaian daya tidak akan mulai. Untungnya, posisi "mA" dan "uA" di hampir semua instrumen pada skala berada di dekatnya, soket untuk mengukur pada kedua rentang adalah sama, sehingga Anda dapat memulai pengontrol dengan aman pada batas "mA", dan ketika mulai tidur, klik "uA "- ini terjadi cukup cepat sehingga pengontrol tidak punya waktu untuk kehilangan daya dan menyalakan ulang.

Harap dicatat bahwa jika pengontrol mengalami lonjakan aktivitas, metode ini tidak berlaku. Misalnya, pengawas waktu disetel ulang setiap 15 detik dalam firmware perangkat - pada saat ini, multimeter mengatur untuk menunjukkan sesuatu di wilayah 27 μA, yang, tentu saja, tidak ada hubungannya dengan cuaca di Mars. Jika terjadi sesuatu yang sewenang-wenang pada sistem Anda lebih sering dari sekali setiap 5-10 detik, multimeter hanya akan berbohong.

Cara lain untuk mengukur statis(Saya langsung menyorot kata ini) konsumsi dengan multimeter adalah ukuran penurunan pada shunt eksternal. Jika Anda ingin mengukur arus ultra kecil pada skala beberapa mikroamp, maka Anda perlu meletakkan shunt besar (misalnya, 1 kOhm), dan bersamaan dengan itu - sebuah dioda Schottky dalam koneksi langsung. Jika shunt turun lebih dari 0,3 V, dioda akan terbuka dan membatasi penurunan tegangan, dan hingga 0,3 V Anda dapat mengukur drop dengan aman dengan multimeter dalam kisaran millivolt, 1 mV = 1 μA.

Sayangnya, itu tidak akan bekerja untuk mengukur penurunan pada shunt impedansi rendah dengan multimeter khas - perangkat kelas menengah, bahkan jika mereka menunjukkan sesuatu di bawah 100 μV, akurasi dalam kisaran ini sangat disesalkan. Jika Anda memiliki perangkat desktop yang bagus yang dapat menampilkan 1 uV, Anda tidak lagi membutuhkan saran saya.

Namun, statika baik, tetapi bagaimana dengan dinamika? Bagaimana cara mengevaluasi efek yang sama dari frekuensi yang berbeda pada konsumsi daya rata-rata?

Semuanya rumit di sini.

Mari kita tuliskan persyaratan dasar:

  • kisaran saat ini setidaknya 1 μA - 100 mA (10 ^ 5)
  • periode pengukuran tidak lebih dari 10 μs
  • drop tegangan tidak lebih tinggi dari 100 mV
  • durasi pengukuran - tidak terbatas

Jika kita langsung menerjemahkannya ke dalam angka, kita mendapatkan ADC yang relatif cepat dan tidak kurang dari 18-bit dengan bias input kurang dari 30 μV, ujung depan analog yang mampu mengukur tegangan dari 1 μV, dan antarmuka cepat ke komputer yang memungkinkan kita mentransfer semua ini dan simpan.

Dan semua ini untuk sekali pakai.

Anda tahu, ya, mengapa hal-hal seperti itu tidak terletak di setiap sudut sepuluh dolar? Keysight N6705C pada pendekatan pertama memenuhi persyaratan kami, hanya biayanya $ 7960.

Dari solusi anggaran, misalnya, SiLabs mengintegrasikan pengukuran saat ini ke dalam debugnya - karakteristik Sistem Pemantauan Energi Lanjut (AEM) mereka bergantung pada model debugging khusus, dan mereka memiliki masalah terbesar dengan kecepatan pengukuran. Dalam "starter kit" lama, STK3300 / 3400 hanya 100 Hz, pada debug yang lebih baru, STK3700 / 3800 (mudah dikenali oleh textolite hitam) - 6,25 kHz, dan pada model lama dari seri Debug DK dapat mencapai hingga 10 kHz, tetapi juga biayanya mereka sudah $ 300 +. Untuk tugas-tugas serius, SiLabs secara resmi merekomendasikan Keysight yang disebutkan di atas.

Pada prinsipnya, perangkat seperti itu dapat dirancang sendiri - pertama-tama, Anda memerlukan op-amp yang sangat baik dengan bias input minimal, seperti OPA2335. Op amp seperti itu ditempatkan pada shunt yang sama 2-3 buah dengan faktor amplifikasi yang berbeda, semuanya luka pada input ADC yang berbeda (dengan pendekatan ini sangat mungkin untuk menggunakan mikrokontroler built-in), maka setiap kali data diambil, ditentukan secara programal mana dari op amp dalam hal ini. saat ini tidak kelebihan beban, bacaan dari itu dihitung.

Masalah kecepatan transfer data ke komputer diselesaikan dengan cukup sederhana - karena untuk tujuan praktis kami terutama tertarik pada konsumsi rata-rata sistem dalam kehidupan nyata, pembacaan mikrodetik dapat dikumpulkan dalam mikrokontroler on-board meter dan rata-rata aritmatika untuk beberapa skala milidetik yang masuk akal dapat dikirim.

Selain itu, seperti yang diperlihatkan oleh praktik, sangat berguna untuk memiliki meter-logger, walaupun sederhana dan tidak terlalu akurat, tetapi selalu ada di tangan - agar tidak mendapatkan kejutan dengan beberapa jenis perubahan firmware yang rusak karena penghematan energi.

Sebagai contoh, kami membangun satu ke adaptor USB standar kami UMDK-RF, yang terus-menerus digunakan ketika debugging firmware - ia sudah memiliki programmer SWD dengan dukungan untuk protokol DAPLink, jembatan USB-UART dan logika manajemen daya, masing-masing, ia mendapat meteran konsumsi hampir gratis. Meteran itu sendiri adalah shunt 1 Ohm dan penguat INA213 (gain 50 kali, nol offset khas 5 μV):



Penguat terhubung langsung ke input ADC mikrokontroler (STM32F042F6P6), proses ADC dengan periode 10 μs menggunakan pengatur waktu perangkat keras, dan naik melalui USB data rata-rata adalah output untuk interval 100 ms. Akibatnya, mengubah sesuatu dalam logika firmware, Anda bisa merokok atau minum kopi, meninggalkan perangkat di atas meja, dan kembali, lihat jadwal seperti ini:



Keakuratan perangkat "bebas" seperti itu, tentu saja, tidak tinggi - dengan ADC 12-bit dan satu amplifier, kuantum minimum adalah 16 μA, tetapi sangat berguna untuk secara cepat dan teratur mengevaluasi perilaku perangkat debugged dari sudut pandang konsumsi energi. Pada akhirnya, jika Anda melakukan kesalahan pada firmware atau perangkat, maka dengan jaminan yang sangat tinggi, Anda akan dapat keluar dari unit microamps setidaknya ratusan, dan ini akan terlihat jelas.



Bonus bagus lainnya adalah karena data dikirim ke port COM virtual dalam bentuk teks (nilai dalam microamps), Anda dapat memposisikan jendela terminal di sebelah jendela yang memperlihatkan konsol perangkat dan melihat konsumsi daya pada saat yang sama dengan men-debug pesan.

Saya membual tentang ini karena suatu alasan, tetapi untuk menawarkan semua orang yang ingin menggunakan programmer Debugger minimal (dan sangat murah!) Ini dalam proyek mereka sendiri.

Anda dapat menggambar diagram di sini ( sumber dalam DipTrace ), seret keluar firmware di sini (umdk-rf brunch, ketika membangun target adalah UMDK-RF, berdasarkan proyek dap42 ). Meskipun diagram dibuat secara kacau, saya harap poin utamanya jelas, firmware ditulis dalam C menggunakan libopencm3 dan dirakit dengan arm-none-eabi-gcc yang biasa. Sebagai fungsi tambahan, firmware memiliki manajemen daya, menangkap sinyal kelebihan dari kunci kontrol dan memasukkan pengontrol yang terhubung ke dalam bootloader aslinya dengan menekan satu tombol.

NB: jika Anda ingin tombol boot untuk membawa controller sendiri programmer ke dalam bootloader-nya secara teratur, itu harus memiliki polaritas koneksi yang berubah, opsi byte pengeditan controller pada boot pertama dan input program ke bootloader dihapus, dan polaritas interupsi untuk reguler fungsi tombol ini.

Anda dapat melihat bagaimana arus diukur pada sepasang op-amp dengan faktor penguatan berbeda (misalnya, untuk meningkatkan debugger yang dijelaskan di atas untuk tugas Anda), di sini (halaman 9), opsi alternatif yang lebih tradisional - dengan satu op-amp dan ADC 24-bit yang mahal - TI memilikinya (EnergyTrace di halaman 5).

PS Harap dicatat bahwa selama melakukan debug dengan UART atau JTAG / SWD yang terhubung, arus kecil juga dapat bocor melalui kaki mereka, yang tidak akan terjadi selama pengoperasian perangkat yang sebenarnya. Jadi, pada UMDK-RF, sekitar 15 μA bocor ke SWD (dan karenanya, dalam foto header, pengukuran dengan multimeter dilakukan pada versi lama board, tanpa SWD), dan pada STM32 Nucleo ada kasus dengan aliran palsu melalui SWD sekitar 200 μA . Papan debug yang digunakan untuk pengukuran harus diperiksa untuk fitur-fitur tersebut - baik dengan memutuskan jalur antarmuka mereka, jika ada kemungkinan seperti itu, atau dengan membandingkan hasilnya dengan konsumsi perangkat yang diukur tanpa menginstalnya untuk debugging, misalnya, dengan multimeter dalam mode statis.

Alih-alih sebuah kesimpulan


Saya harap Anda sudah mengerti kesalahan apa yang Anda buat dengan memilih pemrograman mikrokontroler sebagai spesialisasi utama Anda.

Source: https://habr.com/ru/post/id430218/


All Articles