Kata pengantar

Pada tutorial penyematan terakhir saya mengatakan bahwa jika Anda ingin melakukan pengembangan tertanam dengan serius,Anda perlu melupakan sedikit tentang abstraksi perangkat keras, sehingga Anda bisa mendapatkan akses penuh untuk mempelajari struktur tingkat rendah untuk mengembangkan dasar yang kuat di bidang ini.

Dalam tutorial ini, ikuti baris ini untuk tidak menggunakan abstraksi perangkat keras dan IDE.

Alat yang Anda perlukan

Dibandingkan dengan tutorial sebelumnya, Anda memerlukan lebih banyak perlengkapan:

  1. Papan Arduino dengan kabelnya
  2. Sebuah potensiometer
  3. Sebuah dipimpin
  4. Resistor 220 ohm (minimum).
  5. Beberapa kabel jumper

Ide

Bagaimana kita bisa melihat kecerahan led? Biasanya sinyal digital dapat berupa 0V atau 5V, yang berarti hidup atau mati. Apakah mungkin untuk melihat spektrum kecerahan antara tegangan ini?

Dengan sinyal digital tentu tidak.

Jika tidak memungkinkan, bagaimana kita bisa mewujudkan proyek ini?

Tenanglah, Nak. Biar saya jelaskan.

Untungnya kita hidup dalam kata analog, di mana segala sesuatunya tidak hanya hidup atau mati. Jadi, kita bisa mendapatkan sinyal analog untuk mengontrol kecerahan led.

Tapi, bagaimana kita bisa menghasilkan tegangan variabel untuk mengontrol led?

Pertanyaan bagus! Saat itulah potensiometer dipasang. Ini akan bertanggung jawab untuk menghasilkan ketegangan variabel ini.

Pemancar potensi

Ini adalah alat utama yang kita perlukan untuk dapat menghasilkan tegangan antara 0V dan 5V.

Mengapa?

Karena potensiometer hanyalah resistansi variabel, kita dapat membuat pembagi tegangan variabel, yang merupakan rangkaian klasik dari kelas elektronik Anda. Diagram rangkaiannya adalah sebagai berikut:

Analog-to-Digital Converter (ADC): jembatan antara dua dunia

Kita akan menggunakan potensiometer untuk mengatur intensitas cahaya, tapi siapa bilang komputer bisa memahami sinyal jenis ini? Dalam artikel ini Saya menjelaskan mengapa komputer tidak dapat memahami hal seperti itu.

Jadi, untuk membuat sinyal ini sesuai sehingga prosesor dapat memahami dan memanfaatkan sinyal tersebut, saat itulah ADC masuk.

Ini adalah jembatan antara dunia nyata, fisik dan analogis dan dunia digital.

Jadi, dengan dan ADC kita memiliki sinyal digital yang dapat diproses oleh CPU.

Modulasi Lebar Pulsa (PWM): pengontrol cahaya sebenarnya

Ok, sekarang kita sudah punya sinyal digital, bagaimana cara mengirimnya ke led agar bisa diatur kecerahannya? Tenang, cara kerjanya tidak seperti itu.

Hal ini karena LED berfungsi secara berbeda dibandingkan bohlam tradisional, misalnya. Tidak seperti bola lampu yang menjadi lebih terang saat Anda mengirimkan lebih banyak daya, LED memiliki penurunan voltase tetap di seluruh bola lampu, dan jika Anda mengirimkan terlalu banyak daya, Anda dapat merusak lampu tersebut.

Dan saat itulah PWM masuk. Singkatnya, PWM adalah teknik untuk mengontrol daya yang dikirim ke perangkat dengan menyalakan dan mematikannya secara cepat (Kita dapat membicarakan topik ini lebih lanjut di artikel lain).

Dan itulah sebenarnya rahasia di balik “mengendalikan” kecerahan LED. Faktanya kecerahannya sendiri tidak dikontrol, yang dilakukannya adalah menghidupkan dan mematikannya dengan sangat cepat sehingga terlihat seperti meredup.

Itulah yang dilakukan PWM — menyalakan dan mematikan LED dengan cepat, dan dengan memvariasikan durasi waktu “hidup” versus waktu “mati”, hal ini dapat menciptakan ilusi peredupan.

Maaf mengecewakanmu, tapi itu hanya ilusi.

Bagaimanapun, setelah bagian-bagiannya dijelaskan, mari kita mulai proyeknya.

Pengaturan

Penyiapannya akan dilakukan menggunakan alat yang disebutkan di awal artikel ini. Berikut gambarnya:

Saya tahu, ini agak ramai, tapi mari kita rangkum cara menyatukannya:

  1. Hubungkan papan Arduino ke komputer Anda menggunakan kabel USB.
  2. Tempatkan LED dan potensiometer pada papan tempat memotong roti. Hubungkan anoda LED ke pin digital 9 (atau pin digital lainnya) di papan Arduino. Hubungkan katoda LED ke resistor 220 (atau lebih tinggi) ohm, lalu sambungkan ujung resistor lainnya ke ground pada papan tempat memotong roti.
  3. Hubungkan pin tengah potensiometer ke pin analog 0 (atau pin analog lainnya) pada papan Arduino. Hubungkan salah satu pin luar potensiometer ke 5V pada papan tempat memotong roti, dan sambungkan pin luar lainnya ke ground.
  4. Hubungkan kabel jumper dari 5V pada papan tempat memotong roti ke sisi lain dari resistor 220 ohm.
  5. Buat kode C Anda lalu jalankan.

Terlalu banyak teori, mari kita mengotori tangan kita

Ini menjadi terlalu teoretis, mari kita ke bagian terbaiknya.

Kode C untuk mewujudkan semua ini

Mari kita lihat kodenya:

#include <avr/io.h>
#include <util/delay.h>

#define LED_PIN PB1
#define POT_PIN PC0

void init_led() {
    DDRB |= (1 << LED_PIN);
    PORTB &= ~(1 << LED_PIN);
}

void init_adc() {
    ADMUX |= (1 << REFS0);
    ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
}

int read_adc() {
    ADCSRA |= (1 << ADSC);
    while (ADCSRA & (1 << ADSC));
    return ADC;
}

void init_pwm() {
    TCCR1A = (1 << COM1A1) | (1 << WGM11);
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
    ICR1 = 255;
    OCR1A = 0;
}

int main(void) {
    init_led();
    init_adc();
    init_pwm();

    while (1) {
        int pot_value = read_adc();
        int brightness = pot_value >> 2;

        OCR1A = brightness;

        _delay_ms(100);
    }

    return 0;
}

Mari kita analisis kode ini bersama-sama, namun sebelumnya: jika Anda tidak melihat tutorial proyek tersemat pertama saya dengan Arduino, silakan baca di sini. Saya menjelaskan bagian dasarnya, seperti penyertaan header dan fungsi utamanya.

#define LED_PIN PB1
#define POT_PIN PC0

Kedua baris ini menggunakan direktif praprosesor #define untuk membuat konstanta nomor pin yang akan digunakan untuk pin digital LED dan pin analog potensiometer.

void init_led() {
    DDRB |= (1 << LED_PIN);
    PORTB &= ~(1 << LED_PIN);
}

Fungsi ini menginisialisasi pin LED dengan menyetel bit terkait di register DDRB ke 1, yang mengonfigurasinya sebagai pin keluaran, dan dengan menyetel bit terkait di register PORTB ke 0, yang menyetel pin ke keadaan rendah. Saya menjelaskan lebih lanjut tentang register tersebut pada artikel tutorial tertanam pertama saya.

void init_adc() {
    ADMUX |= (1 << REFS0);
    ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
}

Fungsi ini menginisialisasi ADC dengan mengatur referensi tegangan untuk menggunakan Vcc sebagai tegangan referensi, mengaktifkan ADC dengan mengatur bit terkait dalam register ADCSRA ke 1, dan mengatur prescaler ADC ke 64 .

int read_adc() {
    ADCSRA |= (1 << ADSC);
    while (ADCSRA & (1 << ADSC));
    return ADC;
}

Fungsi ini membaca nilai analog dari potensiometer dengan mengatur bit konversi awal ADC pada register ADCSRA ke 1, dan menunggu konversi selesai dengan menunggu dalam satu loop selama ADC masih sibuk. Setelah konversi selesai, fungsi mengembalikan nilai 10-bit yang disimpan dalam register ADC.

void init_pwm() {
    TCCR1A = (1 << COM1A1) | (1 << WGM11);
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
    ICR1 = 255;
    OCR1A = 0;
}

Fungsi ini menginisialisasi output PWM dengan mengatur mode pembangkitan gelombang ke PWM cepat dengan nilai tertinggi 0xFF, mengaktifkan output PWM pada pin OCR1A, mengatur prescaler PWM ke 8, dan mengatur siklus kerja awal ke 0.

int main(void) {
    init_led();
    init_adc();
    init_pwm();

    while (1) {
        int pot_value = read_adc();
        int brightness = pot_value >> 2;

        OCR1A = brightness;

        _delay_ms(100);
    }

    return 0;
}

Ini adalah fungsi utama dari program ini. Ini memanggil tiga fungsi inisialisasi, dan kemudian memasuki loop tak terbatas yang membaca nilai potensiometer, menurunkan skalanya ke nilai 8-bit dengan menggeser bit ke kanan sebanyak dua bit, mengatur siklus tugas output PWM ke nilai yang diskalakan. , lalu tunggu selama 100 milidetik sebelum mengulangi perulangan.

Dan bagaimana saya tahu nama register aneh ini? Lembar Data.

file make-up

MCU = atmega328p
F_CPU = 16000000UL
PROGRAMMER_TYPE = arduino
PORT = /dev/ttyACM0
HEXFILE = main.hex
SOURCES = main.c
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) -Wall -Os
AVRDUDE = avrdude

.PHONY: all clean install

all: $(HEXFILE)

$(HEXFILE): $(OBJECTS)
 avr-gcc $(CFLAGS) -o $@ $(OBJECTS)
 avr-objcopy -O ihex $@ $(HEXFILE)

$(OBJECTS): $(SOURCES)
 avr-gcc $(CFLAGS) -c $(SOURCES)

clean:
 rm -f $(OBJECTS) $(HEXFILE)

install: $(HEXFILE)
 $(AVRDUDE) -p $(MCU) -c $(PROGRAMMER_TYPE) -P $(PORT) -b 115200 -D -U flash:w:$(HEXFILE)

Mari kita lihat file make ini.

MCU = atmega328p
F_CPU = 16000000UL
PROGRAMMER_TYPE = arduino
PORT = /dev/ttyACM0
HEXFILE = main.hex
SOURCES = main.c
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) -Wall -Os
AVRDUDE = avrdude

Pertama, kita mendefinisikan variabel kita:

  1. MCU = atmega328p: mendefinisikan mikrokontroler target sebagai ATmega328P.
  2. F_CPU = 16000000UL : menyetel frekuensi jam ke 16 MHz.
  3. PROGRAMMER_TYPE = arduino : menentukan tipe programmer sebagai “arduino”.
  4. PORT = /dev/ttyACM0 : menentukan port serial untuk programmer.
  5. HEXFILE = main.hex : menyetel nama file keluaran menjadi “main.hex”.
  6. SOURCES = main.c : menentukan file kode sumber sebagai “main.c”.
  7. OBJECTS = $(SOURCES:.c=.o) : menentukan file objek sebagai “main.o”.
  8. CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) -Wall -Os : menentukan flag compiler, termasuk mikrokontroler, frekuensi clock, level peringatan, dan level optimasi.
  9. AVRDUDE = avrdude : menentukan perintah avrdude yang digunakan untuk mengunggah kode ke mikrokontroler.
.PHONY: all clean install

Baris ini menentukan target yang bukan file sebenarnya, melainkan hanya perintah yang akan dijalankan.

all: $(HEXFILE)

Baris ini menentukantarget default yang akan dibuat, yang bergantung pada file hex.

$(HEXFILE): $(OBJECTS)
    avr-gcc $(CFLAGS) -o $@ $(OBJECTS)
    avr-objcopy -O ihex $@ $(HEXFILE)

Baris ini menentukan cara membuat file hex dari file objek menggunakan perintah avr-gcc dan avr-objcopy.

$(OBJECTS): $(SOURCES)
    avr-gcc $(CFLAGS) -c $(SOURCES)

Baris ini menentukan cara membuat file objek dari file sumber menggunakan perintah avr-gcc.

clean:
    rm -f $(OBJECTS) $(HEXFILE)

Baris ini menentukan cara membersihkan objek dan file hex menggunakan perintah rm.

install: $(HEXFILE)
    $(AVRDUDE) -p $(MCU) -c $(PROGRAMMER_TYPE) -P $(PORT) -b 115200 -D -U flash:w:$(HEXFILE)

Baris ini menentukancara mengunggah file hex ke mikrokontroler menggunakan avrdude.

Sekarang, Anda siap mengeksekusi. Kamu bisa menulis :

make

Diikuti oleh

make install

Hasil akhir

Sayangnya, saya tidak dapat menempelkan di sini video saya yang menunjukkan proyek sedang berjalan.

Segera saya akan memberikan link ke instagram saya (jika Anda ingin melihat konten harian tentang sistem tertanam, ikuti saya di sini) sehingga Anda dapat melihat videonya.

Anda tetap bisa mengujinya sendiri.

Seperti biasa, terima kasih telah meluangkan waktu untuk membaca saya!

Lebih banyak artikel

  1. Kebenaran pahit yang harus dihadapi jika Anda memulai pengembangan perangkat lunak tertanam
  2. Kuasai dasar-dasar sistem tertanam dengan 2 pertanyaan yang harus ditanyakan ini