Dalam latihan radio amatir, terkadang ada kebutuhan untuk melakukan sesuatu pada mikrokontroler. Jika Anda tidak melakukan kerajinan seperti ini sepanjang waktu, maka Anda harus mencari solusi sirkuit yang sesuai dan perpustakaan yang cocok untuk MK untuk waktu yang lama, sehingga Anda dapat dengan cepat menyelesaikan masalahnya. Baru-baru ini saya ingin membuat saklar antena otomatis. Dalam prosesnya, saya harus menggunakan banyak fitur Atmega MK dalam satu proyek ringkas. Mereka yang mulai mempelajari AVR, beralih dari Arduino atau kadang-kadang program MK dapat menjadi potongan kode yang berguna yang digunakan oleh saya dalam proyek.
Saya memikirkan saklar antena sebagai perangkat yang secara otomatis menghubungkan antena ke transceiver, yang paling cocok untuk rentang kerja gelombang pendek. Saya memiliki dua antena: V terbalik dan Ground Plane, mereka terhubung ke tuner antena MFJ, di mana mereka dapat diaktifkan dari jarak jauh. Ada saklar manual bermerek MFJ, yang ingin saya ganti.
Untuk pengalihan operasional antena, satu tombol terhubung ke MK. Saya mengadaptasinya untuk mengingat antena yang disukai untuk setiap rentang: ketika Anda menekan tombol selama lebih dari 3 detik, antena yang dipilih diingat dan dipilih dengan benar secara otomatis setelah power-up perangkat berikutnya. Informasi tentang kisaran saat ini, antena yang dipilih, dan keadaan penyetelannya ditampilkan pada layar LCD satu baris.
Anda dapat mengetahui kisaran transceiver yang saat ini bekerja dengan cara yang berbeda: Anda dapat mengukur frekuensi sinyal, Anda dapat menerima data melalui antarmuka CAT, tetapi hal paling sederhana bagi saya adalah menggunakan antarmuka transceiver YAESU untuk menghubungkan amplifier eksternal. Ini memiliki 4 garis sinyal, dalam kode biner, yang menunjukkan kisaran saat ini. Mereka memberikan sinyal logis dari 0 hingga 5 volt dan mereka dapat dihubungkan ke kaki-kaki MK melalui sepasang resistor terminating.
Bukan itu saja. Dalam mode transmisi, sinyal PTT dan ALC ditransmisikan melalui antarmuka yang sama. Ini adalah sinyal logis tentang menyalakan pemancar (ditarik ke tanah) dan sinyal analog dari 0 hingga -4V tentang pengoperasian sistem kontrol daya pemancar otomatis. Saya juga memutuskan untuk mengukurnya dan menampilkannya pada LCD dalam mode transmisi.
Selain itu, tuner MFJ dapat mengirimkan sinyal ke remote control yang sedang disetel dan antena disetel. Untuk melakukan ini, panel kontrol perusahaan MFJ memiliki dua LED kontrol. Alih-alih LED, saya menghubungkan optocoupler dan mengirim sinyal dari mereka ke MK, sehingga saya bisa melihat semua informasi di satu layar. Perangkat yang sudah selesai terlihat seperti ini.
Secara singkat tentang buatan sendiri seperti segalanya. Sekarang tentang bagian perangkat lunak. Kode ini ditulis dalam Atmel Studio (Unduhan gratis dari situs web Atmel). Proyek untuk pemula menunjukkan fitur-fitur berikut menggunakan Atmega8 MK yang populer:
- Hubungkan tombol
- Hubungkan input saluran untuk sinyal digital dari transceiver dan tuner
- Menghubungkan output kontrol dari saklar antena
- Menghubungkan satu layar LCD baris
- Koneksi buzzer dan output suara
- Koneksi jalur input analog ADC dan pengukuran tegangan
- Menggunakan interupsi
- Menggunakan timer untuk menghitung waktu tombol ditekan
- Menggunakan Watchdog
- Menggunakan memori non-volatile untuk menyimpan antena yang dipilih
- Menggunakan UART untuk Pencetakan Debug
- Menghemat energi dalam idle MK
Jadi mari kita mulai. Dalam perjalanan teks, akan ada segala macam nama register dan karakteristik konstanta dari MK yang diterapkan. Ini bukan Arduino, sayangnya, Anda harus membaca datasheet di MK. Jika tidak, Anda tidak mengerti apa arti semua register ini dan bagaimana Anda dapat mengubah nilainya. Tetapi struktur program secara keseluruhan akan tetap sama.
Pertama, hubungkan tombol ke MK
Ini yang paling sederhana. Kami menghubungkan satu kontak ke kaki MK, kontak tombol kedua ke tanah. Agar tombol berfungsi, Anda harus mengaktifkan resistor pull-up di MK. Dia akan menghubungkan tombol melalui perlawanan ke +5V bus. Untuk melakukan ini cukup sederhana:
PORTB |= (1 << PB2);
Demikian pula, semua input digital yang dikendalikan oleh gangguan tanah (optocoupler, jalur sinyal dari transceiver, sinyal PTT) ditarik ke bus + 5V. Terkadang lebih baik menyolder resistor yang lebih kecil secara fisik (misalnya 10k) antara input MK dan bus + 5V, tetapi pembahasan masalah ini berada di luar cakupan artikel. Karena semua sinyal input dalam proyek jarang mengubah nilai, mereka didorong ke tanah oleh 10 kapasitor nanofarad untuk melindungi terhadap gangguan.
Sekarang kita memiliki 1 logis pada input PB2, dan ketika Anda menekan tombol, itu akan logis 0. Ketika Anda menekan \ tekan, Anda perlu melacak bouncing kontak tombol, memeriksa bahwa tingkat sinyal tidak berubah dari waktu ke waktu, katakanlah 50 milidetik. Ini dilakukan dalam program seperti ini:
if(!(PINB&(1<<PINB2)) && !timer_on) {
Sekarang hubungkan squeaker
Ini akan memberikan sinyal konfirmasi audio bahwa antena direkam dalam memori MK. Sebuah tweeter hanyalah elemen piezoelektrik. Terhubung melalui resistansi kecil ke kaki MK, dan dengan kontak kedua ke + 5V. Agar buzzer ini berfungsi, Anda harus terlebih dahulu mengkonfigurasi kaki MK untuk menampilkan data.
void init_buzzer(void) { PORTB &= ~(1 << PB0);
Sekarang bisa digunakan. Untuk melakukan ini, fungsi kecil ditulis yang menggunakan waktu tunda untuk mengganti kaki MK dari 0 ke 1 dan sebaliknya. Beralih dengan penundaan yang diperlukan memungkinkan untuk menghasilkan sinyal audio 4 kHz dengan durasi sekitar seperempat detik pada output MK, yang merupakan suara elemen piezoelektrik.
void buzz(void) {
Agar fungsi penundaan berfungsi, jangan lupa sertakan file header dan tetapkan kecepatan prosesor konstan. Itu sama dengan frekuensi resonator kuarsa yang terhubung ke MK. Dalam kasus saya, ada kuarsa 16MHz.
#ifndef F_CPU # define F_CPU 16000000UL #endif #include <util/delay.h>
Kami terhubung ke antena switching relay MK
Di sini Anda hanya perlu mengkonfigurasi kaki MK untuk bekerja di jalan keluar. Relai buluh dihubungkan ke kaki ini melalui transistor yang menguatkan dengan cara standar.
void init_tuner_relay(void) { PORTB &= ~(1 << PB1);
Koneksi tampilan
Saya menggunakan layar LCD 160 karakter single-line 1601, diekstraksi dari perangkat keras lama. Ia menggunakan pengontrol HD44780 yang terkenal, untuk manajemen yang banyak perpustakaan tersedia di jaringan. Beberapa orang baik menulis perpustakaan kontrol tampilan ringan, yang saya gunakan dalam proyek ini. Menyiapkan pustaka dikurangi menjadi menunjukkan dalam file header HD44780_Config.h jumlah kaki MK yang terhubung ke pin tampilan yang diinginkan. Saya menerapkan koneksi tampilan melalui 4 jalur data.
#define Data_Length 0 #define NumberOfLines 1 #define Font 1 #define PORT_Strob_Signal_E PORTC #define PIN_Strob_Signal_E 5 #define PORT_Strob_Signal_RS PORTC #define PIN_Strob_Signal_RS 4 #define PORT_bus_4 PORTC #define PIN_bus_4 0 #define PORT_bus_5 PORTC #define PIN_bus_5 1 #define PORT_bus_6 PORTC #define PIN_bus_6 2 #define PORT_bus_7 PORTC #define PIN_bus_7 3
Fitur dari instance tampilan saya adalah bahwa satu baris pada layar ditampilkan sebagai dua baris 8 karakter, sehingga buffer layar perantara dibuat dalam program untuk pekerjaan yang lebih mudah dengan layar.
void init_display(void) { PORTC &= ~(1 << PC0);
Fungsi update_display () memungkinkan Anda untuk menampilkan konten buffer di layar. Nilai byte dalam buffer adalah kode ASCII dari karakter output.
Debug mencetak output ke port COM
MK memiliki UART dan saya menggunakannya untuk men-debug program. Saat menghubungkan MK ke komputer, Anda hanya perlu mengingat bahwa level sinyal pada output MK berada dalam standar TTL, dan bukan RS232, sehingga Anda memerlukan adaptor sederhana. Saya menggunakan adaptor USB-Serial, mirip sepenuhnya pada aliexpress. Setiap program terminal, misalnya dari Arduino, cocok untuk membaca data. Kode pengaturan port UART:
#define BAUD 9600 #include <stdio.h> #include <stdlib.h> #include <avr/io.h> // UART RS232 void uart_init( void ) { /* // UBRRH = 0; UBRRL = 103; //9600 16 */ #include <util/setbaud.h> UBRRH = UBRRH_VALUE; UBRRL = UBRRL_VALUE; #if USE_2X UCSRA |= (1 << U2X); #else UCSRA &= ~(1 << U2X); #endif //8 , 1 , UCSRC = ( 1 << URSEL ) | ( 1 << UCSZ1 ) | ( 1 << UCSZ0 ); // // UCSRB = ( 1 << TXEN ) | ( 1 <<RXEN ); UCSRB = ( 1 << TXEN ); } int uart_putc( char c, FILE *file ) { // while( ( UCSRA & ( 1 << UDRE ) ) == 0 ); UDR = c; wdt_reset(); return 0; } FILE uart_stream = FDEV_SETUP_STREAM( uart_putc, NULL, _FDEV_SETUP_WRITE ); stdout = &uart_stream;
Setelah mengatur aliran output, Anda dapat menggunakan printf yang biasa untuk mencetak ke port:
printf( "Start flag after reset = %u\r\n", mcusr_mirror );
Program ini menggunakan pencetakan bilangan real. Pustaka biasa tidak mendukung mode keluaran ini, jadi saya harus menghubungkan pustaka lengkap ketika menghubungkan proyek. Benar, itu benar-benar meningkatkan jumlah kode, tapi saya punya banyak memori, jadi itu tidak kritis. Dalam opsi tautan Anda perlu menentukan baris:
-Wl,-u,vfprintf -lprintf_flt
Bekerja dengan penghitung waktu dan interupsi
Untuk menghitung interval waktu dalam suatu program, penting untuk memiliki penghitung waktu. Diperlukan untuk melacak bahwa tombol ditekan selama lebih dari 3 detik dan, karena itu, Anda perlu mengingat pengaturan baru dalam memori non-volatile. Untuk mengukur waktu dalam gaya AVR, Anda perlu mengonfigurasi penghitung denyut dari penghasil clock dan interupsi yang akan dieksekusi ketika penghitung mencapai nilai yang ditetapkan. Saya mengatur timer sehingga menghasilkan interupsi sekitar sekali per detik. Interrupt handler sendiri menghitung jumlah detik yang berlalu. Variabel timer_on mengontrol on / off timer. Penting untuk tidak lupa mendeklarasikan semua variabel yang diperbarui di interrupt handler sebagai volatile, jika tidak kompiler dapat "mengoptimalkan" mereka dan program tidak akan berfungsi.
Nilai pass_secs diperiksa dalam loop utama program. Ketika tombol ditekan, timer mulai dan kemudian dalam siklus program utama nilai timer diperiksa saat tombol ditekan. Jika nilai ini melebihi 3 detik, maka EEPROM ditulis, dan timer berhenti.
Terakhir tetapi tidak kalah pentingnya, setelah semua inisialisasi, Anda perlu mengaktifkan interupsi dengan perintah sei ().
Pengukuran Level ALC
Itu dibuat menggunakan konverter analog-ke-digital (ADC) bawaan. Saya mengukur tegangan pada input dari ADC7. Harus diingat bahwa Anda dapat mengukur nilai dari 0 hingga 2.5V. dan tegangan input saya dari -4V ke 0V. Oleh karena itu, saya menghubungkan MK melalui pembagi tegangan paling sederhana pada resistor, sehingga level tegangan pada input MK berada pada level tertentu. Lebih lanjut, saya tidak membutuhkan akurasi tinggi, jadi saya menerapkan konversi 8-bit (cukup membaca data hanya dari register ADCH). Sebagai sumber referensi, saya menggunakan ion internal pada 2.56V, ini sedikit menyederhanakan perhitungan. Agar ADC berfungsi, pastikan untuk menghubungkan kapasitor 0,1 μF ke kaki REF di permukaan tanah.
ADC dalam kasus saya berfungsi terus-menerus, melaporkan akhir konversi dengan memanggil interupsi ADC_vect. Merupakan praktik yang baik untuk meratakan nilai beberapa siklus konversi untuk mengurangi kesalahan. Dalam kasus saya, saya menyimpulkan rata-rata 2500 transformasi. Semua kode ADC terlihat seperti ini:
Menggunakan EEPROM
Ini adalah memori non-volatile di MK. Lebih mudah menggunakannya untuk menyimpan segala macam pengaturan, nilai koreksi, dll. Dalam kasus kami, ini hanya digunakan untuk menyimpan antena yang dipilih untuk rentang yang diinginkan. Untuk tujuan ini, array 16 byte dialokasikan di EEPROM. Tetapi Anda dapat mengaksesnya melalui fungsi-fungsi khusus yang ditentukan dalam file header avr / eeprom.h. Saat startup, MK membaca informasi tentang pengaturan yang disimpan ke dalam RAM dan menyalakan antena yang diinginkan, tergantung pada kisaran saat ini. Ketika tombol ditekan untuk waktu yang lama, nilai baru dicatat dalam memori, disertai dengan sinyal suara. Saat menulis ke EEPROM, interupsi dinonaktifkan untuk berjaga-jaga. Kode Inisialisasi Memori:
EEMEM unsigned char ee_bands[16];
Potongan kode pemrosesan untuk menekan tombol selama 3 detik dan menulis ke memori:
if (!(PINB&(1<<PINB2)) && passed_secs >= 3) {
Menggunakan Watchdog
Bukan rahasia lagi bahwa di bawah kondisi interferensi elektromagnetik yang kuat, MK dapat membeku. Ketika radio sedang beroperasi, ada gangguan sehingga "setrika mulai berbicara", jadi Anda harus memastikan restart MK dengan hati-hati jika terjadi hang. Pengawas waktu melayani tujuan ini. Menggunakannya sangat sederhana. Pertama, sertakan file header avr / wdt.h dalam proyek. Di awal program, setelah semua pengaturan selesai, Anda harus memulai timer dengan memanggil fungsi wdt_enable (WDTO_2S), dan kemudian ingat untuk mengatur ulang secara berkala dengan memanggil wdt_reset (), jika tidak maka akan me-restart MK. Untuk debugging untuk mengetahui mengapa MK itu restart, Anda dapat menggunakan nilai register MCUSR khusus, nilai yang dapat diingat dan kemudian output ke cetak debug.
Hemat energi untuk pecinta lingkungan
Sementara MK tidak sibuk dengan apa pun, ia bisa tertidur dan menunggu gangguan berikutnya. Dalam hal ini, sedikit energi listrik dihemat. Agak, tapi mengapa tidak menggunakannya dalam proyek. Apalagi itu sangat sederhana. Sertakan file header avr / sleep.h. Badan program terdiri dari satu loop tak terbatas di mana Anda perlu memanggil fungsi sleep_cpu (), setelah itu MC tertidur sedikit dan loop utama berhenti sampai gangguan berikutnya terjadi. Mereka terjadi selama pengoperasian timer dan ADC, sehingga MK tidak akan tidur untuk waktu yang lama. Mode hibernasi ditentukan ketika MK diinisialisasi dengan memanggil dua fungsi:
set_sleep_mode(SLEEP_MODE_IDLE);
Itu saja untuk saat ini. Saya beralih, itu berhasil bekerja di stasiun radio amatir saya tanpa kegagalan. Saya berharap materi yang diberikan akan bermanfaat bagi pemula.
73 de R2AJP