Putar musik .wav dari kartu memori SDCard dengan arduino

jenis file suara menurut sistem kompres data-nya terdiri atas file suara terkompresi dan file suara tidak dikompresi (compressed/uncompresses), yaitu metode penyimpanan data suara digital yang bertujuan memperkecil ukuran file suara dan dengan penurunan kualitas suara sekecil-kecilnya.

File suara tidak dikompres memiliki keunggulan kualitas yang asli selain itu tidak memerlukan proses dekompresi yang rumit untuk mengambil/memutar-nya menjadi suara.

WAV (waveform audio file format) adalah contoh file suara yang tidak dikompres. karena masih menyimpan data aslinya jenis file ini memiliki ukuran yang besar. tidak seperti file suara terkompresi seperti .mp3, .aac, .ogg, .wma yang mmembutuhkan algoritma/codec untuk membuka datanya, .wav bisa langsung digunakan. sehingga .wav sangat cocok untuk perangkat mikrokontroller seperti arduino yang memiliki kecepatan dan memory yang kecil.

play .wav dengan arduino

file wav disimpan dan di ambil data-nya dengan metode PCM (pulse code modulation). file wav memiliki struktur header 44 byte yang berisi informasi jum;ah channel (mono/stereo), sample rate, bit per sampel dan informasi lainnya.

Khusus penggunaan arduino untuk memutar  file .wav dengan kecepatan 16MHz hanya efektif di sample rate 32.000, 16.000, 8.000 dengan kanal mono dan 8 bit per sampel.

Skema memutar file suara .wav menggunakan arduino dari microSD

Rangkaian speaker bukan stereo (tapi unbalanced audio connection)

(seandainya menggunakan ampli) jangan hubungkan ground arduino dan ground ampli jika keluaran suara ke speaker menggunakan 2 kabel pin 9 dan 10 (gunakan salah satu saja jika ground terhubung)

koding memainkan suara dari kartu memori berbasis arduino:


#define pinSpeakerA     9
#define pinSpeakerB     10

#define pinCS           8
#define faktorKali      2

#include <SD.h>
#include <SPI.h>


bool suaraDimainkan;
uint32_t sampleCounter;
byte ulangPerSampel;
byte ulang;

struct  HeaderWAV
{
  char                RIFF[4];
  unsigned long       ChunkSize;
  char                WAVE[4];
  char                fmt[4];
  unsigned long       Subchunk1Size;
  unsigned short      AudioFormat;
  unsigned short      NumOfChan;
  unsigned long       SamplesPerSec;
  unsigned long       bytesPerSec;
  unsigned short      blockAlign;
  unsigned short      bitsPerSample;
  char                Subchunk2ID[4];
  unsigned long       Subchunk2Size;

};

HeaderWAV headerWAV;
File fileSuara;


void setup(void)
{
  pinMode(pinSpeakerA, OUTPUT);
  pinMode(pinSpeakerB, OUTPUT);

  Serial.begin(9600);
  Serial.println("Memutar file suara .wav pada kartu memory SDCard dengan arduino");
  Serial.println("https://www.semesin.com/project/");

  if (!SD.begin(pinCS))
  {
    Serial.println("SD fail");
    return;
  }
}

void loop(void)
{
  if (!suaraDimainkan)
  {
    mainkanSuara("pulang.wav");
  }
  else
  {
    lanjutkanSuara();
  }
}

void mainkanSuara(char *namaFile)
{
  fileSuara = SD.open(namaFile);
  if ( !fileSuara )
  {
    Serial.println("File suara tidak ditemukan");
    return 0;
  }

  byte *alamat = (byte*)&headerWAV;
  for (byte i = 0; i < sizeof(headerWAV); i++)
  {
    byte data = fileSuara.read();
    *alamat++ = data;
  }
  Serial.print("namaFile=");
  Serial.println(namaFile);
  Serial.print("headerWAV.SamplesPerSec=");
  Serial.println(headerWAV.SamplesPerSec);
  Serial.print("headerWAV.NumOfChan=");
  Serial.println(headerWAV.NumOfChan);
  Serial.print("headerWAV.bitsPerSample=");
  Serial.println(headerWAV.bitsPerSample);
  Serial.print("headerWAV.Subchunk2Size=");
  Serial.println(headerWAV.Subchunk2Size);

  ulangPerSampel = 32000L / headerWAV.SamplesPerSec;
  ICR1 = 256;
  TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11);
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

  sampleCounter = 0;
  ulang = 0;
  suaraDimainkan = true;
}

void lanjutkanSuara()
{
  if (TIFR1 & _BV(TOV1))
  {
    TIFR1 |= _BV(TOV1);
    if (!(ulang++ % ulangPerSampel))
    {
      if (sampleCounter++ >= headerWAV.Subchunk2Size)
      {
        Serial.println("Selesai");
        stopPlayback();
      }
      else
      {
        byte data = fileSuara.read();

        uint16_t sample = data;
        OCR1B = 256 - sample;
        OCR1A = sample;
      }
    }
  }
}


void stopPlayback()
{
  TIMSK1 &= ~_BV(OCIE1A);
  TCCR1B &= ~_BV(CS10);
  OCR1A = 128;
  OCR1B = 128;

  fileSuara.close();
  digitalWrite(pinSpeakerA, LOW);
  digitalWrite(pinSpeakerB, LOW);

  suaraDimainkan = false;
}



contoh file .wav mono 16kHz 8 bit:
pulang.wav

Pengontrolan tegangan menggunakan PWM pada arduino

Pengontrolan tegangan berfungsi untuk menjaga kestabilan tegangan keluaran ke beban sehingga beban bisa bekerja semestinya. Contohnya jika beban lampu yang intensitas cahayanya bergantung kepada tegangan, maka dengan tegangan yang stabil akan mengeluarkan cahaya yang stabil pula.

Hal yang menyebabkan ketidakstabilan tegangan diantaranya :

  1. Perubahan beban (penambahan dan pengurangan)
  2. Perubahan nilai masukan (input)
  3. Faktor luar seperti interferensi.

Faktor yang mempengaruhi keandalan pengontrolan tegangan :

  1. Kecepatan respon dari pengontrol tegangan terhadap perubahan yang terjadi, semakin cepat semakin baik.
  2. Sistem koreksi yang digunakan, seperti PID, fuzzy
  3. Karakteristik sensor dan beban yang digunakan

Pengontrolan tegangan dengan arduino

Pengendalian tegangan harus memiliki masukan sensor tegangan dan aktuator kontrol tegangan. Pada aplikasi arduino pembacaan tegangan menggunakan ADC dan aktuasi kontrol tegangan menggunakan PWM.

Dalam contoh ini, sistim koreksi tegangan menggunakan metode proporsional, yaitu semakin besar selisih tegangan dan input maka akan semakin besar pula penambahan nilai PWM.

skema sistem kontrol tegangan mengguakan arduino:

Sketch / koding Penngendalian Tegangan dengan PWM:

#define pinSensorTegangan     0
#define pinOutputPWM          9
#define setTegangan           2.5//volt
#define faktorProporsional    0.1

float keluaran;

void setup() {
  pinMode(pinOutputPWM, OUTPUT);
  
  Serial.begin(9600);
  Serial.println("Sumber tegangan stabil (automatic voltage regulator) menggunakan kontrol proporsional");
  Serial.println("http://www.semesin.com/project/");
  Serial.println();

  keluaran = setTegangan;
}

void loop() {
  uint16_t adc = analogRead(pinSensorTegangan);
  float tegangan = map(adc, 0, 1024, 0, 500)/100.0;
  float selisih = setTegangan - tegangan;
  float proporsional = faktorProporsional * selisih;
  
  keluaran += proporsional;
  keluaran = constrain(keluaran, 0, 5);
  byte keluaranPWM = map(keluaran*100, 0, 5*100, 0, 255);
  analogWrite(pinOutputPWM, keluaranPWM);

  //Plot serial, hapus untuk menambah kecepatan
  Serial.print(tegangan);
  Serial.print(", ");
  Serial.print(keluaranPWM);
  Serial.println();
  delay(10);
}

Hasil Plot sinyal PWM (merah) dan tegangan keluaran (biru) terhadap perubahan beban.

Suara Arduino

Arduino merupakan platform elektronik yang dirancang untuk memudahkan pengontrolan berbagai perangkat.

Hardware arduino mikrokontroller yang memiliki port masukan (input)  dan port keluaran (output). Perangkat keras arduino juga dilengkapi dengan fitur-fitur bawaan chip mikrokontroler atau diprogram secara software, seperti komunikasi serial, SPI, I2C, ADC, TIMER.

Sebagai perangkat digital, arduino juga mampu berperilaku sebagai perangkat multimedia terbatas, yakni hanya sebagai pengontrol melalui protokol yang disediakan. Salah satu perangkat multimedia yang mampu ditangani oleh arduino adalah suara.

Arduino audio / suara bisa dihasilkan dalam 2 metode, yaitu arduino sebagai pembangkit suara dan arduino sebagai pengontrol modul suara.

Suara PWM arduino

Port output arduino mampu melewatkan arus 40mA setiap pinnya, artinya arduno masih mampu membangkitkan suara untuk keperluan headset. Selain keuntungan itu, arduino juga memiliki memory walaupun kapasitasnya kecil, seperti pada arduino uno mampu menampung kurang dari 8detik data PCM 8bit 8KHz yang membutuhkan 8.000 byte flash memory setiap detiknya. Untuk efesiensi memory bisa dengan menurunkan sampling rate atau menggunakan sistem kompresi ADPCM.

prinsip kerja Suara PCM Arduino dengan PWM:

  1. Data suara disimpan dalam memory flash.
  2. Dibutuhkan dua timer, timer1 berfungsi mengatur waktu sampling (misalnya 8KHz, 16KHz dst), dan timer 2 yang berfungsi mengatur PWM Sesuai ukuran bit sampling (misalnya 8bit dan 16 bit).
  3. Data PWM berubah dan dikirim saat timer1 selesai 1 periode sampling.

Keterbatasan PCM arduino adalah : waktu * ukuran sampling tidak bisa melebihi besar clock arduino 16MHz.

Contoh rangkaian suara arduino langsung :

 

Modul Suara WTV020

 

Modul ini menggunakan format suara .ad4 yang disimpan dalam kartu memory microSD (kapasitas terbatas). Pengontrolan menggunakan pin-pin kontrol dengan mode operasi yang tersedia:

  1. MP3 mode
  2. Key mode(3 group of voice)
  3. Key mode(5 group of voice)
  4. Loop play mode
  5. Two line serial mode

Modul suara ISD

Modul ISD menggunakan chip yang memiliki fitur rekam dan membangkitkan suara. terdiri dari beberapa seri dan kapasitas.

Modul mini MP3 TF Player

 

Mini Mp3 TF Player banyak disukai karena murah dan mudah dalam operasionalnya, mampu menggerakkan speaker 0.5Watt, dan menggunakan protokol Serial frame. Data suara disimpan dalam format MP3 / WAV dalam microSD.

Modul Suara VS1053

VS1053 merupakan chip audio player yang powerfull dengan kualitas suara yang bagus. Data suara dalam format MP3 yang disimpan dalam microSD.

Perbandingan modul suara arduino

Masih terdapat beberapa modul suara yang bisa disandingkan dengan arduino, yang disebutkan diatas bisa mewakili yang paling umum digunakan dalam perancangan perangkat multimedia berbasis arduino.

Kualitas suara yang dihasilkan menjadi alasan utama dari pemilihan modul audio untuk arduino, dan menurut penulis kualitas modul VS1053 paling baik dan layak digunakan sebagai media informasi. sedangkan modul lainnya efektif digunakan dalam pengembangan perangkat karena harganya relatif lebih murah.

Kualitas suara bisa ditingkatkan dengan memperhatikan hal berikut:

  1. Filter keluaran suara
  2. Power supply / catu daya yang cukup dan tidak saling menmpengaruhi dengan modu lainnya.
  3. Penggunaan speaker yang sesuai, kalau perlu gunakan box.
  4. Konversi suara mono ke stereo atau sebaliknya menggunakan cara koneksi yang benar.
  5. Konversi suara single supply ke balance double supply atau sebaliknya menggunakan cara konversi yang benar.

Dimmer PWM arduino

Dimmer adalah rangkaian elektronik yang memodifikasi bentuk sinyal ac murni menjadi sinyal terpotong-potong sehingga daya keluaran bisa diatur. Pemotongan sinyal ac ini berguna sebagai peredup lampu, memperlambat motor, mengatur pemanasan dan lainnya.

Dimmer yang lebih komplek menggunakan PWM sebagai pengendalinya. PWM bisa dihasilkan oleh rangkaian SCR, chip/IC PWM atau mikrokontroller. Dimmer PWM ini mampu menghasilkan tingkatan daya yang kecil, sehingga pengontrolan menjadi lebih presisi.

Dimmer PWM bisa dikategorikan menjadi dua macam yaitu :

  1. Penyalaan berdasarkan titik nol.
  2. Penyalaan bebas.

Penyalaan berdasarkan titik nol

Waktu penyalaan bergantung pada saat sinya menyentuh nilai nol. Maka dibutuhkan mekanisme untuk mendeteksi waktu sinyal tersebut bernilai 0.

Komponen SCR memiliki sifat forward blocking, forward conduction, dan reverse blocking, maka komponen ini cocok digunakan sebagai dimmer elektronik.

Rangkaian dimmer lampu ac yang memanfatkan sifat SCR:

Pada aplikasi dimmer digital, perlintasan titik nol harus dideteksi terlebih dahulu sebelum melakukan menyalaan, Pendeteksian nilai nol bisa dilakukan dengan rangkaian zero crossing detector / ZCD berikut :

Perancangan dimmer PWM mengikuti kaidah berikut:

  1. Waktu penyalaan, sinyal bolak-balik (AC) senantiasa bergerak naik dan turun, maka sinyal pengontrol PWM haruslah dimulai saat sinyal AC meninggalkan nilai nol
  2. Frekuensi AC, Sinyal pengontrol PWM juga harus memiliki frekuensi tepat dengan frekuensi sinyal AC (listrik)

Kendala membuat dimmer metode zero cross adalah :

  1. frekuensi ac 220v dari penyedia listrik seperti PLN bisa saja berubah-ubah. pada contoh dimmer lampu 220v, intensitas cahaya menjadi tidak konsisten. Untuk mengantisipasi ini sebaiknya dilakukan pengukuran frekuensi secara berkala.
  2. Sulit untuk sinkronisasi frekuensi jala listrik dengan frekuensi pengontrol, karena keterbatasan perhitungan digital, misalnya faktor pergeseran frekuensi akibat pembagian bilangan yang tidak sempurna. Sebagai contoh perangkat digital akan sulit mencapai frekuensi 50,00019 Hz.
  3. Memakai resources mikrokontroller seperti arduino untuk mendeteksi ZCD terus menerus.
  4. Jika ada kesalahan setting waktu penyalaan (program diinterupsi) maka beban seperti lampu akan berkedip.
  5. Pada duty cycle rendah, untuk dimmer lampu akan terlihat flicker karena perbandingan waktu on  sangat kecil dibandingkan waktu off.

Rangkaian dimmer arduino dengan beban lampu:

Penampakan modul dimmer lampu:

Penghasil sinyal PWM yang favorit adalah arduino, karena mampu menghitung frekuensi dan melakukan penyesuaian apabila ada pergeseran frekuensi:

Sketch / koding dimmer lampu arduino
fitur:

  1. input zcd dari semua pin (tidak harus pin int0/pin 9 dan int1/pin 10)
  2. input kontrol berupa duty cycle (rentang 0.0 – 100.0 %)
#define PWM         9
#define ZCD         10 // A0 = 14, A5 = 19
#define frekuensi   50 //50 Hz
#define inputSerial 0

volatile uint16_t dutyCycle;
#define maxDutyCycle    ((16000000L / (2 * 1024L *  frekuensi)) - 1)

volatile intptr_t *portPWM;
byte bitPWM;

void setup() {
  Serial.begin(9600);
  Serial.println("Dimmer arduino");
  Serial.println("https://www.semesin.com/project/");
  Serial.println();

  TCCR2A = _BV(WGM21);
  TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
  OCR2A = maxDutyCycle;
  OCR2B = setDutyCycle(0);
  TIMSK2 = _BV(OCIE2B);

  *digitalPinToPCMSK(ZCD) |= bit (digitalPinToPCMSKbit(ZCD));
  PCIFR  |= bit (digitalPinToPCICRbit(ZCD));
  PCICR  |= bit (digitalPinToPCICRbit(ZCD));

  portPWM = (volatile intptr_t *) portOutputRegister(digitalPinToPort(PWM));
  bitPWM = digitalPinToBitMask(PWM);

  pinMode(PWM, OUTPUT);
}

void loop() {
#if inputSerial

  if (Serial.available())
  {
    int data = Serial.parseInt();
    dutyCycle = setDutyCycle(data);
  }
  
#else

  for (byte i = 20; i <= 100; i++)
  {
    dutyCycle = setDutyCycle(i);
    delay(20);
  }
  for (byte i = 99; i != 20; i--)
  {
    dutyCycle = setDutyCycle(i);
    delay(20);
  }
  
#endif

}
uint16_t setDutyCycle(uint8_t dutyCycle)
{
  return maxDutyCycle - (1.0 * dutyCycle / 100 * (maxDutyCycle - 1)) + 1;
}

#if defined(__AVR_ATmega328P__)
#  if ((ZCD >= 0) & (ZCD <= 7))
ISR (PCINT2_vect)
#  elif ((ZCD >= 8) & (ZCD <= 13))
ISR (PCINT0_vect)
#  elif ((ZCD >= 14) & (ZCD <= 19))
ISR (PCINT1_vect)
#  endif
#endif
{
  OCR2B = dutyCycle;
  TCNT2 = 0;
}

ISR (TIMER2_COMPB_vect)
{
  *portPWM |= bitPWM;
  delayMicroseconds(30);
  *portPWM &= ~bitPWM;
}

Penyalaan bebas

Waktu penyalaan dimmer tidak dipengaruhi oleh nilai nol,

Rangkaian dimmer ac sederhana :

Sirkit melalui dioda disebut juga penyearah setengah gelombang, yang menghasilkan kondisi dimmer setengah terang. Rangkaian ini biasanya digunakan pada solder, heatgun untuk pemanasan awal.

Pengaturan dimmer PWM lebih diutamakan pada frekuensi PWM-nya. Dimmer lampu akan terlihat berkedip jika frekuensi tidak sama. Untuk mengatasi pemasalahan tersebut rangkaian peredup lampu (Dimmer) didesain dengan penggunaan frekuensi yang lebih tinggi dari frekuensi sinyal AC tanpa memperhatikan waktu nol dan nilai frekuensinya.

Sinyal PWM bisa diperoleh dari rangkaian pembangkit PWM (PWM generator) atau dari mikrokontroller seperti arduino. Aplikasi rangkaian dimmer lampu arduino (rangkaian dimmer arduino) bisa menggunakan perintah analogWrite().

Berikut komponen elektronika yang digunakan dalam perancangan dimmer PWM lampu 220v:

  1. Dioda 1N5408 4 buah
  2. Dioda 1N4007
  3. Dioda zener 10V
  4. Resistor 220 ohm 2 buah
  5. Resistor 330 ohm
  6. Resistor 68 Kohm
  7. Kapasitor 2.2 uH
  8. Optocoupler 4N35
  9. Mosfet IRF 830
  10. Lampu dan Fitting

Berikut skema rangkaian dimmer lampu dc/ac yang dikontrol PWM:

Sumber tegangan negatif menggunakan PWM (Arduino)

Sumber tegangan negatif beguna untuk :

  1. Pengatur kontras (contrast adjustment) pada LCD karakter
  2. Sumber tegangan negatif pada opamp simetris
  3. Dan keperluan lain

Suplai tegangan negatif bisa diperoleh dari:

  1. Baterai dengan menjadikan terminal positif (+) menjadi ground, maka otomatis terminal negatif (-) menjadi sumber tegangan negatif.
  2. Memanfaatkan rangkaian charge pump.

rangkaian charge pump:

Rangkaian ini memerlukan suplai PWM yang bisa dihasilkan dari arduino dengan analogWrite().

Agar keluaran tegangan negatif bisa diatur, maka tambahkan potensio 10KΩ pada keluarannya.

Rangkaian Dimmer lampu yang dikendalikan oleh sinyal PWM digital

Lampu merupakan komponen yang mengubah energi listrik menjadi energi cahaya. Untuk mengontrol intensitas cahaya lampu kita biasa menggunakan dimmer/peredup. Dimmer umumnya dikendalikan oleh potensio, yang mengontrol waktu penyalaan SCR.

Rangkaian dimmer ac:

Untuk mengontrol intensitas cahaya lampu menggunakan sinyal PWM digital memiliki beberapa kendala yaitu :

  1. Waktu penyalaan, sinyal bolak-balik (AC) senantiasa bergerak naik dan turun, maka sinyal pengontrol PWM haruslah dimulai saat sinyal AC meninggalkan nilai nol
  2. Frekuensi AC, Sinyal pengontrol PWM juga harus memiliki frekuensi tepat dengan frekuensi sinyal AC (listrik)

Akibat dari frekuensi yang tidak pas tepat adalah intensitas cahaya lampu yang tidak rata.

Permasalahan waktu penyalaan bisa dideteksi dengan rangkaian zero crossing detector (ZCD), dan permasalahan frekuensi AC bisa dideteksi dengan melakukan pengukuran rentang frekuensinya.

Namun perangkat digital juga memiliki tick point yang tidak singkron dengan sinyal AC misalnya faktor pergeseran frekuensi akibat pembagian bilangan yang tidak sempurna. Sebagai contoh perangkat digital akan sulit mencapai frekuensi 50,00019 Hz.

Untuk mengatasi pemasalahan tersebut rangkaian peredup lampu (Dimmer) didesain dengan penggunaan frekuensi yang lebih tinggi dari frekuensi sinyal AC tanpa memperhatikan waktu nol dan nilai frekuensinya.

Sinyal PWM bisa diperoleh dari rangkaian pembangkit PWM (PWM generator) atau dari mikrokontroller seperti arduino. Aplikasi rangkaian dimmer lampu arduino (rangkaian dimmer arduino) bisa menggunakan perintah analogWrite().

Berikut komponen elektronika yang digunakan dalam perancangan dimmer PWM lampu 220v:

  1. Dioda 1N5408 4 buah
  2. Dioda 1N4007
  3. Dioda zener 10V
  4. Resistor 220 ohm 2 buah
  5. Resistor 330 ohm
  6. Resistor 68 Kohm
  7. Kapasitor 2.2 uH
  8. Optocoupler 4N35
  9. Mosfet IRF 830
  10. Lampu dan Fitting

Berikut skema rangkaian dimmer lampu dc/ac yang dikontrol PWM:

 

update: http://www.semesin.com/project/2018/05/01/dimmer-pwm-arduino/

Mengatur kecepatan motor DC 5V menggunakan PWM

Untuk menggerakkan motor DC diperlukan driver, driver motor adalah rangkaian elektronika yang mampu menghasilkan arus yang besar untuk belitan motor. driver yang umum digunakan adalah formasi jembatan (full bridge) seperti chip L293, L298.

Salah satu rangkaian favorit (sederhana) untuk menggerakkan motor
dc adalah rangkaian push pull atau rangkaian totem pole.

skema rangkaian totem pole (rangkaian tarik-ulur) menggunakan transistor:

kombinasi transistor yang bisa digunakan adalah NPN BD139 dan PNP BD140 yang mampu melewatkan arus hingga 1A. Rangkaian ini memiliki kekurangan yaitu tegangan keluaran sama dengan tegangan masukan (input) dikurangi tegangan Vbe sekitar 0.6v.

Agar rangkaian pushpull/totempole bisa menghasilkan tegangan output lebih besar misalnya 12 volt, bisa melengkapinya dengan opamp.

Skema rangkaian pushpull dengan opamp:

Jika dikombinasikan dengan PWM dari arduino, maka rangkaian ini berfungsi sebagai Pengatur kecepatan motor dc yang memiliki fungsi kecepatan, selain itu juga fungsi maju dan mundur.

Untuk mengatur kecepatan motor dc menggunakan arduino, rangkaian disusun menjadi dua sisi (untuk polaritas positif dan negatif) dan dua input pwm.

Skema pengontrol kecepatan motor dc dengan arduino:

berikut contoh sketch atau program yang bisa diaplikasikan.

#define pinMotorA 9
#define pinMotorB 10

bool motorMaju = false;
bool motorHidup = false;
char chrKecepatan[5];
byte Kecepatan;

void setup() {
  Serial.begin(9600);
  Serial.println("Mengatur kecepatan motor DC 5V menggunakan PWM dilengkapi aksi maju-mundur");
  Serial.println("dengan rangkaian sederhana menggunakan Arduino dan 4 transistor");
  Serial.println("entri [M] untuk maju");
  Serial.println("entri [m] untuk mundur");
  Serial.println("entri [Kxxx] untuk set kecepatan, xxx = 0 s/d 255");
  Serial.println("entri [+] untuk menambah kecepatan 10 angka");
  Serial.println("entri [-] untuk kurangi kecepatan 10 angka");
  Serial.println("entri [B] untuk berhenti");
  Serial.println("http://www.semesin.com/project");

  pinMode(pinMotorA, OUTPUT);
  pinMode(pinMotorB, OUTPUT);
}

void loop() {
  if(Serial.available())
  {
    char c = Serial.read();
    if(c == 'M')
    {
      motorMaju = true;
      Serial.println("Motor maju");
      motorHidup = true;
    }
    else if(c == 'm')
    {
      motorMaju = false;
      Serial.println("Motor mundur");
      motorHidup = true;
    }
    else if(toupper(c) == 'K')
    {
      delay(10);
      Serial.readBytesUntil('\n', chrKecepatan, sizeof(chrKecepatan));
      Kecepatan = String(chrKecepatan).toInt();
      Serial.print("Set kecepatan = ");
      Serial.println(Kecepatan);
    }
    else if(c == '+')
    {
      if(Kecepatan <= 245)
      {
        Kecepatan += 10;
      }
      Serial.print("Set kecepatan = ");
      Serial.println(Kecepatan);
    }
    else if(c == '-')
    {
      if(Kecepatan >= 10)
      {
        Kecepatan -= 10;
      }
      Serial.print("Set kecepatan = ");
      Serial.println(Kecepatan);
    }
    else if(toupper(c) == 'B')
    {
      digitalWrite(pinMotorA, LOW);
      digitalWrite(pinMotorB, LOW);
      motorHidup = false;
      Serial.println("Motor berhenti");
    }
  }
  if(motorHidup)
  {
    if(motorMaju)
    {
      digitalWrite(pinMotorB, LOW);
      analogWrite(pinMotorA, Kecepatan);
    }
    else
    {
      digitalWrite(pinMotorA, LOW);
      analogWrite(pinMotorB, Kecepatan);
    }
  }

}

jika terjadi kedala Arduino me-reset ketika running, bisa diakibatkan Arduino kekurangan catu daya (power supply).

fungsi analogWrite() dengan variabel duty cycle dan frekuensi (aplikasi PWM)

Perintah analogWrite() dengan variabel duty cycle dan frekuensi pada pin 9 atau 10 ini berguna untuk membangkitkan sinyal PWM (PWM Generator) yang sangat variatif dari 0.24 Hz hingga 160kHz duty cycle 0.0 ~ 100.0%,sedangkan frekuensi 160kHz hingga 8MHz dengan duty cycle terbatas.

Modifikasi analogWrite ini menggunakan timer1 sebagai penanda waktunya, sehinggga hanya akan mempengaruhi pin 9 dan 10 saja, dan tidak bisa dikombinasikan dengan fungsi PWM arduino biasa.

Parameter PWM yang digunakan:

  1. pin, hanya pin 9 dan 10
  2. dutyCyclePersen, nilai 0..100 adalah lebar pulsa on dalam persen
  3. frekuensi, nilai 0.24 hingga 8000000 (8Mhz)

berikut sketch/program fungsi analogWrite serbaguna

#define PWM_1 9
#define PWM_2 10

void setup() {
  Serial.begin(9600);
  Serial.println("fungsi analogWrite() dengan variabel duty cycle dan frekuensi pada pin 9 atau 10");
  Serial.println("Pada penggunaan kombinasi pin 9 dan 10,");
  Serial.println("maka frekuensi yang di set terakhir yang akan digunakan");
  Serial.println("http://www.semesin.com/project");
}

void loop() {
  //analogWrite(pin, dutyCyclePersen, frekuensi)
  analogWrite(PWM_1, 50, 1000);
  while(1);
}

void analogWrite(byte pin, double dutyCyclePersen, double frekuensi)
{
  if(frekuensi > 244.0)
  {
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
    ICR1 = (16000000L/(frekuensi)) - 1;
  }
  else if(frekuensi > 30.0)
  {
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11);
    ICR1 = (16000000L/(frekuensi * 8)) - 1;
  }
  else if(frekuensi > 3.0)
  {
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11) | _BV(CS10);
    ICR1 = (16000000L/(frekuensi * 64)) - 1;
  }
  else if(frekuensi > 0.95)
  {
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12);
    ICR1 = (16000000L/(frekuensi * 256)) - 1;
  }
  else if(frekuensi > 0.23)
  {
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12) | _BV(CS10);
    ICR1 = (16000000L/(frekuensi * 1024)) - 1;
  }
  TCCR1A &= ~_BV(WGM10);
  TCCR1A |= _BV(WGM11);
  if(pin == 9)
  {
    pinMode(9, OUTPUT);
    TCCR1A |= _BV(COM1A1);
    OCR1A = (dutyCyclePersen/100) * (ICR1 + 1);
  }
  if(pin == 10)
  {
    pinMode(10, OUTPUT);
    TCCR1A |= _BV(COM1B1);
    OCR1B = (dutyCyclePersen/100) * (ICR1 + 1);
  }
}

Pengaturan frekuensi PWM pada arduino (fungsi analogWrite(pin, value) tetap seperti biasa)

Perintah analogWrite(pin, onTime) pada arduino berfungsi membangkitkan sinyal PWM pada pin dimaksud. biasanya frekuensi yang dibangkitkan adalah :

  1. 976.5625Hz untuk arduino Uno pin 5 dan 6 (clock 16MHz)
  2. 488.28125Hz untuk arduino Uno pin 3, 9,10 dan 11 (clock 16MHz)

adakalanya kita membutuhkan frekuensi berbeda dari standar ini. Dengan mengatur register TCCRnB kita bisa mengatur frekuensi PWM arduino sehingga diperoleh frekuensi maksimum 62500Hz pada pin 5 dan 6 Arduino Uno, dan minimum 30.517578125Hz pada pin 3,9,10 dan 11 Arduino Uno. Formula/rumus yang dapat dipergunakan adalah :

A. Timer 0 Arduino Uno

frekuensi = io_clock/(N * TOP)

B. Timer 1 dan 2 Arduino Uno

frekuensi = io_clock/(2 * N * TOP)

dengan io_clock = 16Mhz dan TOP = 256

dengan merubah nilai N kita bisa mendapatkan harga frekuensi yang berbeda:

Penggunaan perintah analogWrite(pin, value) tetap seperi biasa (nilai value berkisar antara 0 ~ 255).

catatan : merubah register Timer 0 akan berdampak langsung terhadap fungsi delay(), millis() dan micros()

A.  Arduino UNO

Nomor urut pembagi Pembagi frekuensi (Hz)
Timer 0, pin 5 dan 6
1 1 62500
2 8 7812.5
3* 64 976.5625
4 256 244.140625
5 1024 61.03515625
Timer 1, pin 9 dan 10
1 1 31250
2 8 3906.25
3* 64 488.28125
4 256 122.0703125
5 1024 30.517578125
Timer 2, pin 3 dan 11
1 1 31250
2 8 3906.25
3 32 976.5625
4* 64 488.28124
5 128 244.140625
6 256 122.0703125
7 1024 30.517578125

tanda * adalah nilai default

B. Arduino Mega

—Menyusul

cara penggunaannya:

  1. Ketahui Timer yang digunakan (contoh pin 5 terintegrasi pada Timer 0).
  2. Catat nilai nomor urut pembagi sesuai dengan frekuensi yang diinginkan
  3. masukkan kedalam baris sketch

TCCR0B = TCCR0B & B11111000 | Nomor-urut-pembagi; (TCCR0B = Timer 0, TCCR1B = Timer 1, TCCR2B = Timer 2)

contoh: TCCR0B = TCCR0B  & B11111000 | 1;

contoh dalam sketch/program:

int pinPWM = 5;

void setup() {
  pinMode(pinPWM,OUTPUT);
}

void loop() {
  analogWrite(pinPWM,128);
  TCCR0B = (TCCR0B & 0b11111000) | 1;

  while(1);
}

atau menggunakan fungsi yang fleksibel berikut:

void setPwmFrequency(int pin, int divisor) {
  byte mode;
  if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
    switch(divisor) {
      case 1: mode = 0x01; break;
      case 8: mode = 0x02; break;
      case 64: mode = 0x03; break;
      case 256: mode = 0x04; break;
      case 1024: mode = 0x05; break;
      default: return;
    }
    if(pin == 5 || pin == 6) {
      TCCR0B = TCCR0B & 0b11111000 | mode;
    } else {
      TCCR1B = TCCR1B & 0b11111000 | mode;
    }
  } else if(pin == 3 || pin == 11) {
    switch(divisor) {
      case 1: mode = 0x01; break;
      case 8: mode = 0x02; break;
      case 32: mode = 0x03; break;
      case 64: mode = 0x04; break;
      case 128: mode = 0x05; break;
      case 256: mode = 0x06; break;
      case 1024: mode = 0x07; break;
      default: return;
    }
    TCCR2B = TCCR2B & 0b11111000 | mode;
  }
}