Berapa Tegangan Kerja Arduino

Berapakah tegangan kerja Arduino?

Tegangan kerja untuk Arduino Nano dan Arduino UNO adalah 5 volt. Tegangan yang dapat diberikan ke pin-pin Arduino adalah minimum 0 volt, maksimum 5 volt. Perkecualian adalah sebagai berikut: pin RESET dapat menerima tegangan sampai 13 volt. Pin VIN dapat menerima tegangan sampai 20 volt karena di pin tersebut ada regulator DC untuk mengubah tegangan masuk menjadi 5 volt.

Arduino Nano dan Arduino UNO menggunakan prosesor ATmega328. Batas maksimum tegangan pada ATmega328 dapat dilihat di datasheet prosesor ATmega328, di bagian “Absolute Maximum Ratings”. Kutipannya sebagai berikut:

ATmega328 absolute maximum rating
ATmega328 absolute maximum rating

Tegangan pada VIN atau POWER IN tidak langsung dihubungkan ke prosesor ATmega328, melainkan melalui regulator DC. Jadi tegangan maksimumnya tergantung komponen regulator DC yang dipakai.

Pin POWER IN dihubungkan ke regulator 5 volt (NCP1117 pada Arduino UNO dan UA78M05 pada Arduino Nano). NCP1117 maksimal menerima tegangan input 20 volt. UA7805 maksimal menerima input 25 volt. Jika tegangan POWER IN melebihi batas ini, maka regulator 5 volt tersebut akan rusak.

Batas tegangan maksimum pada NCP1117 dapat dibaca pada datasheetnya sebagai berikut:

Tegangan maksimum pada NCP1117
Tegangan maksimum pada NCP1117

Batas tegangan maksimum pada UA78M05 dapat dibaca pada datasheetnya sebagai berikut:

Tegangan maksimal pada UA7805
Tegangan maksimal pada UA7805


Referensi

Apa Itu ADC (Analog to Digital Converter) dan Fungsi ADC

Apa itu ADC

ADC (Analog to Digital Converter) adalah perangkat yang mengubah sinyal analog menjadi sinyal digital. Besaran analog di sini maksudnya adalah besaran yang mempunyai nilai kontinyu pada waktu kontinyu, sedangkan digital di sini maksudnya adalah memiliki representasi diskrit pada waktu yang diskrit.

Perubahan waktu kontinyu menjadi waktu diskrit menggunakan proses pencuplikan (sampling). Perubahan amplitudo kontinyu menjadi amplitudo diskrit menggunakan proses kuantisasi.

Bentuk fisik ADC dapat berupa sebuah chip, bisa juga dibuat menggunakan komponen diskrit (transistor, gerbang logika, op-amp), ataupun sudah menyatu dengan mikrokontroler.

ADC tipe MCP3008 buatan Microchip

Jenis ADC

Jenis-jenis ADC adalah sebagai berikut:

  • Flash
  • Single slope converter
  • Dual slope converter
  • Successive Approximation Register
  • Delta Sigma

Berikut ini contoh skema suatu flash ADC (sumber)

Berikut ini contoh skema suatu SAR ADC (sumber)

Berikut ini contoh skema suatu Integrating ADC (sumber)

Parameter ADC

Parameter-parameter ADC adalah sebagai berikut

  • resolusi: menyatakan berapa jumlah nilai diskrit yang dapat dihasilkan untuk merepresentasikan nilai masukan analog. Umumnya dinyatakan dalam jumlah bit pada output ADC
  • kecepatan sampling: parameter ini menyatakan berapa banyak konversi analog ke digital yang dapat dilakukan setiap detik.

Resolusi

Konsep resolusi ADC dapat dilihat pada contoh ini. Berikut ini contoh pemetaan nilai analog (0 sampai 1.0) ke nilai biner terkait dari suatu ADC 8 bit (sumber)Pencuplikan

Sinyal analog bersifat kontinyu pada domain waktu. Untuk mengubah sinyal analog ini menjadi digital, perlu didefinisikan seberapa cepat nilai digital dicuplik dari sinyal analog. Kecepatan menghasilkan nilai digital ini adalah kecepatan sampling atau frekuensi sampling (sampling rate / sampling frequency).

Sinyal analog dapat dicuplik menjadi sinyal digital dan kemudian dapat dikembalikan lagi ke bentuk analog dengan syarat kecepatan samplingnya lebih tinggi dari dua kali frekuensi maksimum pada sinyal analog tersebut. Kriteria ini adalah disebut juga sebagai teorema pencuplikan Nyquist-Shannon.

Antar Muka ADC

ADC umumnya dipakai bersamaan dengan elemen komputasi seperti mikroprosesor/mikrokontroler ataupun FPGA (Field Programmable Array) . Antar muka antara ADC dengan elemen komputasi dapat dengan berbagai cara, seperti:

  • Terintegrasi dalam 1 chip, seperti ADC pada mikrokontroler ATmega328 di modul Arduino UNO / Arduino Nano / ESP32
  • Bus data mikroprosesor paralel
  • Komunikasi serial I2C (Inter Integrated Circuit)
  • Komunikasi serial SPI (Serial Peripheral Interface)
  • Komunikasi serial proprietary

Contoh ADC terintegrasi adalah mikrokontroler Arduino Nano yang di dalamnya ada ADC 10 bit.

Arduino Nano specimen 1
Arduino Nano

Contoh ADC yang menggunakan komunikasi bus data adalah ADC0804 (sumber). Berikut ini contoh skema rangkaian interkoneksi antara mikroprosesor dengan ADC0804

Bentuk fisik ADC0804
Bentuk fisik ADC0804

 

Skema rangkaian ADC0804
Skema rangkaian ADC0804

Pada saat ini jarang sekali orang menggunakan teknik ini, karena biasanya mikrokontroler tidak memiliki bus yang dapat diakses.

Contoh ADC dengan bus I2C adalah ADS1115 buatan Texas Instruments . ADC ini banyak dijual sebagai modul yang sudah disolder.

Modul ADS1115
Modul ADS1115

Contoh ADC dengan koneksi SPI  adalah MCP3008 buatan Microchip

MCP3008

Aplikasi ADC

ADC dipakai untuk berbagai aplikasi seperti

  • Perekaman suara
  • Pengolahan sinyal meliputi perekaman, penyimpanan dan pengiriman sinyal melalui media tertentu
  • Instrumentasi ilmiah untuk merekam sinyal dari berbagai sensor

Lebih jauh tentang ADC:

 

Apa fungsi pin pada Arduino?

Fungsi pin pada Arduino adalah menghubungkan sinyal-sinyal dari dalam modul Arduino ke luar dan sinyal dari luar Arduino ke dalam.  Setiap pin pada Arduino memiliki fungsi tertentu.

Berikut ini fungsi-fungsi pin pada Arduino UNO

Nama Port Fungsi Utama
Fungsi Lain
Power Jack catu daya 7 sampai 12 volt  
USB type B catu daya 5 volt & komunikasi serial  
IOREF referensi ADC  
RESET pin reset pada ATmega328  
3V3 supply 3,3 volt  
+5V supply 5 volt  
GND ground  
VIN tegangan masuk 7 sampai 12 volt  
A0 input analog & I/O digital  
A1 input analog & I/O digital  
A2 input analog & I/O digital  
A3 input analog & I/O digital  
A4 input analog & I/O digital SDA untuk I2C
A5 input analog & I/O digital SCL untuk I2C
D19 I/O digital  
D18 I/O digital  
AREF Pin referensi ADC (Analog to Digital Converter)  
D13 I/O digital  
D12 I/O digital  
D11 I/O digital OC2A , MOSI
D10 I/O digital OC1B, SS
D9 I/O digital IC1A
D8 I/O digital CLK0 , ICP1
D7 I/O digital AIN1
D6 I/O digital AIN0
D5 I/O digital T1
D4 I/O digital T0
D3 I/O digital INT1
D2 I/O digital INT0
D1 I/O digital TXD
D0 I/O digital RXD
 

Berikut ini daftar pin pada Arduino UNO R3

Pinout Arduino UNO
Pinout Arduino UNO

Apa fungsi pin analog pada Arduino?

  • Pin analog pada Arduino berfungsi menerima sinyal listrik berupa tegangan analog. Tegangan ini diubah oleh ADC (Analog to Digital Converter) menjadi angka digital. ADC pada Arduino UNO dan Arduino Nano memiliki resolusi 10 bit, jadi tegangan analog tersebut akan dibaca oleh perangkat lunak sebagai angka integer 0 sampai dengan 1023.
  • Pin analog pada Arduino UNO hanya ada 6 buah, yaitu A0 , A1, A2, A3, A4 dan A5

Apa fungsi pin digital pada Arduino?

  • Pin digital pada Arduino berfungsi menerima atau mengirim sinyal listrik digital. Tegangan pada pin digital akan dibaca oleh perangkat lunak sebagai angka 0 (jika input tegangan rendah mendekati 0 volt) atau 1 (jika input tegangan tinggi mendekati 5 volt). Fungsi untuk membaca tegangan pada pin digital adalah digitalRead(). Tegangan pada pin digital juga dapat diubah oleh perangkat lunak Arduino dengan fungsi digitalWrite().
  • Semua port pada Arduino dapat difungsikan sebagai input digital maupun output digital.

 

 

Apa itu PWM dan fungsinya?

Apa yang dimaksud dengan PWM, dan apa fungsinya?

PWM (Pulse Width Modulation) adalah modulasi suatu sinyal digital dengan cara mengubah-ubah lebar pulsa tergantung nilai inputnya.

Berikut ini contoh sinyal PWM:

Sinyal PWM memiliki frekuensi tetap. Lebar pulsa diubah-ubah dengan cara mengubah duty-cycle dari sinyal tersebut. Rentang input PWM adalah 0 sampai 100%. Outputnya adalah sinyal dengan frekuensi tetap, namun duty cycle mengikuti input.

Fungsi sinyal PWM di antaranya adalah sebagai berikut:

  • sinyal kendali untuk motor servo radio control
  • modulasi untuk pengiriman data pada telekomunikasi.
  • mengatur daya yang diberikan kepada suatu beban, misal untuk mengendalikan kecepatan putaran suatu motor listrik
  • regulasi tegangan. Tegangan output dapat diatur dengan mengubah duty cycle sinyal.
  • mengatur kecerahan lampu LED

Berikut ini contoh servo motor yang biasa dipakai di aplikasi radio control:

modul motor tersebut memiliki 3 input: VCC, GND dan PWM. Sudut pada poros ditentukan oleh duty cycle pada sinyal PWM.

Referensi

 

Apa perbedaan fungsi void setup () dan void loop ()?

Perbedaan antara fungsi ‘void setup()’ dan ‘void loop()’ pada Arduino adalah sebagai berikut:

  • ‘void setup()’ berisi kode/program yang hanya dijalankan sekali ketika Arduino dinyalakan. Biasanya fungsi setup() ini berisi inisialisasi hardware dan inisialisasi variabel global.
  • ‘void loop()’ berisi kode /program yang dijalankan berulang-ulang tanpa ada berhenti. Biasanya menjalankan fungsi utama dari Arduino tersebut.

Selain setup() dan loop(), sebenarnya ada juga fungsi interupsi yang hanya dijalankan ketika interupsi tertentu diaktifkan. Interupsi eksternal dapat diaktifkan dengan fungsi attachInterrupt(). Interupsi timer dapat diaktifkan dengan library TimerInterrupt.

Sebagai contoh adalah program lampu kedip sederhana dari Arduino sebagai berikut:

void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(1000);                      // wait for a second
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
  delay(1000);                      // wait for a second
}

Pada program tersebut, setup() berisi inisialisasi pin output untuk lampu LED.

loop() berisi pekerjaan utama sistem mikrokontroler Arduino tersebut, yaitu menyalakan dan mematikan lampu LED berulang-ulang tanpa berhenti.

Referensi

Apa perbedaan pin analog dan digital pada Arduino?

Berikut ini perbedaan pin analog dan digital pada Arduino adalah sebagai berikut:

  • Pin analog menerima sinyal listrik berupa tegangan analog. Tegangan ini diubah oleh ADC (Analog to Digital Converter) menjadi angka digital. ADC pada Arduino UNO dan Arduino Nano memiliki resolusi 10 bit, jadi tegangan analog tersebut akan dibaca oleh perangkat lunak sebagai angka integer 0 sampai dengan 1023.
  • Pin digital pada Arduino menerima sinyal listrik digital. Tegangan pada pin digital akan dibaca oleh perangkat lunak sebagai angka 0 (jika input tegangan rendah mendekati 0 volt) atau 1 (jika input tegangan tinggi mendekati 5 volt).

Sinyal input pada pin analog dibaca dengan fungsi analogRead(), hasilnya adalah angka integer dari 0 sampai 1023.

Sinyal input pada pin digital dibaca dengan fungsi digitalRead(), hasilnya adalah angka 0 atau 1.

Pin analog pada Arduino UNO dan Nano dapat difungsikan sebagai input analog maupun digital.

Pin digital pada Arduino UNO dan Nano hanya dapat difungsikan sebagai input digital.

Referensi

Berapa banyak pin analog pada Arduino UNO?

Berapa banyak pin analog pada Arduino UNO?

Jawab: jumlah pin analog pada Arduino UNO adalah 6 buah yaitu A0, A1, A2 A3, A4 dan A5

Berikut ini posisi pin-pin pada Arduino UNO:

Daftar pin pada Arduino UNO R3
Daftar pin pada Arduino UNO R3

Pin analog terdapat pada bagian kiri bawah. Pin analog tersebut multi fungsi , yaitu dapat berfungsi sebagai pin analog (input) maupun pin digital (input dan output).

Apa yang dimaksud dengan pin pada Arduino?

Yang dimaksud dengan pin pada Arduino adalah kontak elektrik yang terdapat pada modul Arduino. Kontak elektrik ini berfungsi untuk menyambungkan sinyal listrik dari modul Arduino ke perangkat lain di luar Arduino.

Berikut ini foto pin berbentuk batang-batang serupa jarum pada Arduino Nano

Arduino Nano tampak samping
Arduino Nano tampak samping

Setiap pin pada Arduino tersebut memiliki fungsi tertentu yang berbeda-beda. Untuk mengetahui fungsinya kita mesti membaca datasheet dari modul Arduino tersebut.

Berikut ini adalah daftar fungsi setiap pin pada Arduino Nano

Kontak elektrik pada Arduino UNO menggunakan lubang-lubang, bukan berupa pin. Berikut ini foto Arduino UNO dengan kontak elektrik berupa plastik hitam yang di dalamnya terdapat kontak elektrik.

Referensi

  • Arduino Nano Pinout https://docs.arduino.cc/hardware/nano
  • Datasheet Arduino Nano https://docs.arduino.cc/resources/datasheets/A000005-datasheet.pdf
  • Electrical Connector https://en.wikipedia.org/wiki/Electrical_connector

 

 

 

 

Apa itu Internet of Things

Internet of Things (IoT) adalah perangkat yang memiliki sensor, kemampuan pengolahan/komputasi, perangkat lunak dan teknologi lain untuk menyambungkan dan mengirimkan data ke perangkat lain dan sistem lain melalui internet atau jaringan komunikasi lainnya.

Bidang ilmu Internet of Things melingkupi elektronika, komunikasi dan ilmu komputer.

Tujuan

Tujuan dari Internet of Things adalah memungkinkan semua benda yang dipakai sehari-hari ke internet untuk melakukan pertukaran informasi.

Aplikasi

Contoh aplikasi Internet of Things:

  • lampu yang dapat dikendalikan dari jarak jauh melalui smartphone
  • Fabrikasi cerdas (smart manufacturing)
  • Memonitor aset-aset untuk dapat melakukan perawatan aset sebelum mengalami kerusakan (perawatan pencegahan dan perawatan terprediksi).
  • Jaringan distribusi elektrik cerdas
  • Kota cerdas
  • Logistik yang tersambung ke jaringan komunikasi
  • Rantai pasok cerdas
  • Pertanian cerdas
  • Kesehatan
  • Industri retail
  • Transportasi

Referensi

  • Internet of Things https://en.wikipedia.org/wiki/Internet_of_things
  • https://www.oracle.com/id/internet-of-things/what-is-iot/
  • https://www.ibm.com/topics/internet-of-things

Mengapa sensor PIR hanya bereaksi pada tubuh manusia saja?

Sensor PIR (Passive Infra Red) hanya bereaksi pada tubuh manusia saja karena sensor tersebut dilengkapi filter radiasi yang dapat mendeteksi radiasi infra merah dari tubuh manusia.

Hewan peliharaan seperti kucing dan anjing memiliki temperatur antara 38,3 sampai dengan 39,2 derajat Celcius, sehingga dapat juga dideteksi oleh sensor PIR yang sama.

Jadi sebenarnya sensor PIR dapat mendeteksi tubuh manusia dan hewan yang memiliki temperatur di sekitar 37 derajat Celcius

Penjelasan

Setiap benda memancarkan radiasi tergantung temperaturnya. Manusia normal memiliki suhu tubuh normal sekitar 37 derajat Celcius. Panas dari tubuh manusia ini memancarkan radiasi infra merah dengan panjang gelombang tertentu. Manusia memancarkan radiasi inframerah dengan panjang gelombang antara 3 sampai 50 mikron.

Most research suggests that humans emit infrared radiation to the tune of between 3-50 microns.
Kebanyakan radiasi di panjang gelombang 9.5 mikrometer. sumber: (https://www.ceramicx.com/information/media/white-papers/infrared-heating-for-humans/)

Rumus hubungan antara panjang gelombang dengan temperatur dikenal dengan “hukum Wien untuk perpindahan” dengan rumus sebagai berikut:

Penjelasan tentang rumus ini dapat dibaca di artikel “Wien’s displacement_law

Konsep radiasi dari suatu benda dapat diperdalam di artikel “Radiasi benda hitam

Sensor PIR

Sensor PIR seperti LHI 778 dirancang untuk mendeteksi radiasi dengan panjang gelombang antara 7um sampai 14 um

Sensor LHI 778

 

Sensor LHI778 ini dipakai di modul PIR seperti “HC-SR501” https://components101.com/sensors/hc-sr501-pir-sensor

HC-SR501 PIR Sensor
HC-SR501 PIR Sensor

Pada modul HC-SR501, modul LHI778 ini ditambah dengan lensa Fresnel plastik untuk memperbaiki arah deteksi dan rangkaian elektronik untuk memperkuat sinyal dari sensor tersebut. Output dari modul ini dapat langsung dihubungkan ke mikrokontroler seperti Arduino.

 

Kesimpulan

Jadi sensor PIR dapat mendeteksi manusia karena tubuh manusia dengan temperatur 37 derajat Celcius memancarkan radiasi infra merah di sekitar 9,5 mikron yang dapat dideteksi dengan sensor dengan filter khusus. Sensor ini dapat membedakan tubuh manusia dengan benda lain yang memiliki temperatur berbeda. Sensor ini  tidak dapat membedakan tubuh manusia dengan benda lain yang memiliki temperatur sama. 

Referensi

 

 

Pengukuran Kecepatan DAC Internal ESP32

Pengukuran Kecepatan DAC Internal ESP32

Pengukuran V1

pada pengukuran ini menggunakan fungsi library dacWrite()

Kode sebagai berikut

#define DAC1 25

void setup() {
  Serial.begin(115200);
}

void loop() {
  while (1) {
    dacWrite(DAC1, 0);
    dacWrite(DAC1, 4095);
  }
}

Berikut ini hasil pengukuran output analog dari DAC dengan osiloskop

Pengukuran V2

Pada pengukuran ini menggunakan fungsi dac_output_enable() dan dac_output_voltage(). Pada fungsi dacWrite, fungsi dac_output_enable() selalu dipanggil sehingga cukup menghabiskan waktu.

// https://github.com/espressif/arduino-esp32/discussions/7889
// https://dronebotworkshop.com/esp32-dac/
// https://deepbluembedded.com/esp32-dac-audio-arduino-examples/
// https://circuitdigest.com/microcontroller-projects/esp32-timers-and-timer-interrupts

#include <driver/dac.h>

int value = 0;

void setup() {
  dac_output_enable(DAC_CHANNEL_1);
}
void loop() {
  for(;;){
    dac_output_voltage(DAC_CHANNEL_1, 0);
    dac_output_voltage(DAC_CHANNEL_1, 255);
  }
}

Pengukuran output analog dengan osiloskop

Kesimpulan

  • Frekuensi DAC adalah 27,068 kHz dengan fungsi dacWrite()
  • Frekuensi DAC adalah 168,932 kHz dengan fungsi dac_output_voltage()

Referensi

Pengukuran Kecepatan ESP32 dengan ADC MCP3008

Foto perangkat

// kode

Kode

library yang dipakai untuk MCP3008 adalah https://github.com/bakercp/MCP3XXX

Pengukuran Library Original

Pada pengukuran ini digunakan library https://github.com/bakercp/MCP3XXX tanpa perubahan

Kode ada di https://github.com/waskita/embedded/tree/master/esp32-mcp3008-baker-profile-v1

Kode program adalah sebagai berikut:

// library: https://github.com/bakercp/MCP3XXX
#include <MCP3XXX.h>
MCP3008 adc;

void setup() {
  Serial.begin(115200);
  Serial.println("start");
  // Use the default SPI hardware interface.
  adc.begin();
  // Or use custom pins to use a software SPI interface.
  // adc.begin(SS, MOSI, MISO, SCK);
  pinMode(22, OUTPUT); // digital output for monitoring
  pinMode(21, OUTPUT);
}
int counter = 0, last_time = 0, current_time = 0;
float durasi=0;
int jumlah_iterasi=100000;

void loop() {
  for (;;) {

    digitalWrite(22, HIGH);  // turn the LED on (HIGH is the voltage level)
    adc.analogRead(0);
    digitalWrite(22, LOW);  // turn the LED on (HIGH is the voltage level)

    counter = counter + 1;
    if (counter == jumlah_iterasi) {  // tiap 10000x berhenti
      counter = 0;
      current_time = millis();
      durasi = (float)(current_time - last_time) / (float) jumlah_iterasi;
      Serial.print("durasi (ms) ");
      Serial.println(durasi,4);
      last_time = current_time;
    }
  }
}

Hasil pengukuran perioda sebagai berikut

start
durasi (ms) 0.0375
durasi (ms) 0.0370
durasi (ms) 0.0370

Output osiloskop dari output digital sebagai berikut

Pengukuran Library Dimodifikasi

Pada percobaan ini dilakukan perubahan pada library untuk mempercepat proses pembacaan.

Kode ada di https://github.com/waskita/embedded/tree/master/esp32-mcp3008-baker-profile-v2

Kode program utama sebagai berikut:

// Profiling kecepatan konversi ADC MCP3008 di ESP32
// menggunakan modified header dari https://github.com/bakercp/MCP3XXX

#include "MCP3XXXZ.h" // custom header

MCP3008 adc;

void setup() {
  Serial.begin(115200);
  Serial.println("start");
  // Use the default SPI hardware interface.
  adc.begin();
  // Or use custom pins to use a software SPI interface.
  // adc.begin(SS, MOSI, MISO, SCK);
  pinMode(22, OUTPUT); // digital output for monitoring
  pinMode(21, OUTPUT);

  adc.spistart(); // 
}
int counter = 0, last_time = 0, current_time = 0;
float durasi=0;
int jumlah_iterasi=100000;

void loop() {
  for (;;) {

    digitalWrite(22, HIGH);  // turn the LED on (HIGH is the voltage level)
    adc.analogRead(0);
    digitalWrite(22, LOW);  // turn the LED on (HIGH is the voltage level)

    counter = counter + 1;
    if (counter == jumlah_iterasi) {  // tiap 10000x berhenti
      counter = 0;
      current_time = millis();
      durasi = (float)(current_time - last_time) / (float) jumlah_iterasi;
      Serial.print("durasi (ms) ");
      Serial.println(durasi,4);
      last_time = current_time;
    }
  }
}

Kode header sebagai berikut

//
// Copyright (c) 2018 Christopher Baker <https://christopherbaker.net>
//
// SPDX-License-Identifier:	MIT
//


#pragma once


#include <Arduino.h>
#include <SPI.h>


/// \brief A template class supporting MCP3XXX ADC SPI chips.
///
/// \tparam NumBits Number of ADC bits.
/// \tparam NumChannels Number of input channels.
/// \tparam MaxSPIClockSpeed Maximum SPI communication speed rate in Hz.
/// \tparam SPITransferLength The number of bytes transferred over SPI.
template<uint8_t NumBits,
         uint8_t NumChannels,
         uint32_t MaxSPIClockSpeed,
         uint8_t SPITransferLength = 3>
class MCP3XXX_
{
public:
	
    enum
    {
        /// \brief ADC error value.
        ADC_ERROR_INVALID_CHANNEL = -1,

        /// \brief ADC error value.
        ADC_UNSUPPORTED_CONFIGURATION = -2,

        /// \brief Number of ADC bits.
        NUM_BITS = NumBits,

        /// \brief A bit mask based on the number of bits.
        BIT_MASK = (1 << NUM_BITS) - 1,

        /// \brief Number of input channels.
        NUM_CHANNELS = NumChannels,

        /// \brief Maximum SPI communication speed rate in Hz.
        MAX_SPI_CLOCK_SPEED = MaxSPIClockSpeed,

        /// \brief The number of bytes transferred over SPI.
        SPI_TRANSFER_LEGNTH = SPITransferLength
    };


    /// \brief Construct a default MCP3XXX_ device.
    MCP3XXX_()
    {
    }

    /// \brief Destroy the MCP3XXX_ device.
    ~MCP3XXX_()
    {
    }
	
	void spistart(){
		SPI.beginTransaction(SPISettings(MAX_SPI_CLOCK_SPEED, MSBFIRST, SPI_MODE0));
	}
    /// \brief Set up the ADC using default hardware SPI pins.
    ///
    /// Hardware SPI pins vary based on the board being used. These default pins
    /// are represented by the constants SS, MOSI, MISO and SCK.
    ///
    /// \sa https://www.arduino.cc/en/Reference/SPI
    /// \param csPin Chip Select Pin. Default value is SS.
    void begin(uint8_t csPin = SS)
    {
      _useHardwareSPI = true;

      _csPin = csPin;
      _mosiPin = MOSI;
      _misoPin = MISO;
      _sckPin = SCK;

      // Set up pin modes.
      pinMode(_csPin, OUTPUT);

      // Begin software SPI.
      // Initializes the SPI bus by setting SCK, MOSI, and SS to outputs,
      // pulling SCK and MOSI low, and SS high.
      digitalWrite(_csPin, HIGH); // Redundant.
      SPI.begin();
    }

    /// \brief Set up the ADC using custom software SPI pins.
    ///
    /// This method forces the SPI to be accesed via software methods rather
    /// than hardware SPI. This is true, even if the default hardware SPI pins
    /// are used.
    ///
    /// \param csPin Chip Select Pin.
    /// \param mosiPin MOSI pin.
    /// \param misoPin MISO pin.
    /// \param sckPin Clock pin.
    void begin(uint8_t csPin, uint8_t mosiPin, uint8_t misoPin, uint8_t sckPin)
    {
      _useHardwareSPI = false;

      _csPin = csPin;
      _mosiPin = mosiPin;
      _misoPin = misoPin;
      _sckPin = sckPin;

      // Set up pin modes manually.
      pinMode(_csPin, OUTPUT);
      pinMode(_mosiPin, OUTPUT);
      pinMode(_misoPin, INPUT);
      pinMode(_sckPin, OUTPUT);

      // Begin software SPI. We initiate CS Pin HIGH to prepare it to go LOW
      // on our first read.
      digitalWrite(_csPin, HIGH);
    }

    /// \brief Read the analog value.
    ///
    /// Reads a single-ended analog value using the given channel.
    ///
    /// \param channel The channel (channel < NUM_CHANNELS) to read.
    /// \returns values [0, MAX_VALUE) on success or an error code on failure.
    uint32_t analogRead(uint8_t channel) const
    {
        if (channel < NUM_CHANNELS)
          return _read(channel, false);
        return ADC_ERROR_INVALID_CHANNEL;
    }

    /// \brief Read a differential analog value by specifying the IN+ channel.
    ///
    /// Consecutive channel pairs can be differentially read. For instance, if
    /// inPositiveChannel == 0, inNegativeChannel will be 1.
    /// If inPositiveChannel == 1, then inNegativeChannel will be 0. Thus if
    /// inPositiveChannel is odd, inNegativeChannel == (inPositiveChannel - 1).
    /// if inPositiveChannel is even, inNegativeChannel == (inPositiveChannel + 1).
    ///
    /// \param inPositiveChannel The channel that should be input positive.
    /// \returns Differential values. See the data sheet for information on how
    ///          to interpret these return values.
    uint32_t analogReadDifferential(uint8_t inPositiveChannel) const
    {
        if (inPositiveChannel < NUM_CHANNELS)
          return _read(inPositiveChannel, true);
        return ADC_ERROR_INVALID_CHANNEL;
    }

    /// \returns the number of ADC channels.
    size_t numChannels() const
    {
        return NUM_CHANNELS;
    }

    /// \returns the number of ADC bits.
    size_t numBits() const
    {
        return NUM_BITS;
    }

private:
    MCP3XXX_(const MCP3XXX_&);
    MCP3XXX_& operator = (const MCP3XXX_&);

    /// \brief Read the value from the given channel using the given mode.
    /// \param channel The channel to read.
    /// \param differential If true, use differential read mode.
    uint32_t _read(uint8_t channel, bool differential) const
    {
      // Data transfers are done using "8-bit segments" approach in data sheet.
      // The sent data alignment resuls in correctly aligned return bytes after
      // the SPI transfer.
      uint8_t data[SPI_TRANSFER_LEGNTH];

      // Check for MCP3004
      if (NUM_CHANNELS == 2)
      {
        if (NUM_BITS == 10)
        {
          // Start bit.
          data[0] = 0b01000000;
          // Differential bit.
          data[0] |= (differential ? 0b00000000 : 0b00100000);
          // Channel bit.
          data[0] |= (channel == 0 ? 0b00000000 : 0b00010000);
          // MSBF bit is set to 1. See section 5.1 of the data sheet.
          data[0] |= 0b00001000;
          // It doesn't matter what data[1] is set to.
        }
        else
        {
          return ADC_UNSUPPORTED_CONFIGURATION;
        }
      }
      else
      {
        if (NUM_BITS == 10)
        {
          // The start bit. We position it here to align our output data.
          data[0] = 0b00000001;
          // Set the differential / single bit and the channel bits.
          data[1] = (differential ? 0b00000000 : 0b10000000) | (channel << 4);
          // It doesn't matter what data[2] is set to.
        }
        else
        {
          return ADC_UNSUPPORTED_CONFIGURATION;
        }
      }

      if (_useHardwareSPI)
      {
        // Here we replace the sent data with the received data.
//        SPI.beginTransaction(SPISettings(MAX_SPI_CLOCK_SPEED, MSBFIRST, SPI_MODE0));
//		digitalWrite(21, HIGH);  // turn the LED on (HIGH is the voltage level)
        digitalWrite(_csPin, LOW);
        for (size_t i = 0; i < SPI_TRANSFER_LEGNTH; ++i)
        {
          data[i] = SPI.transfer(data[i]);
        }
        digitalWrite(_csPin, HIGH);
//		digitalWrite(21, LOW);  // turn the LED on (HIGH is the voltage level)
//        SPI.endTransaction();
      }
      else
      {
        // Slower, but can use any pin.
        // We could save a few operations by skipping some digitalWrites(),
        // using bitwise operators and doing direct port-manipulation.
        // But this is used because it is "easier" to read.
        digitalWrite(_csPin, LOW);
        for (size_t i = 0; i < SPI_TRANSFER_LEGNTH; ++i)
        {
          for (size_t j = 8; j-- > 0;)
          {
            // Set MOSI data.
            digitalWrite(_mosiPin, bitRead(data[i], j));
            // Set Clock HIGH.
            digitalWrite(_sckPin, HIGH);
            // Read MISO data.
            bitWrite(data[i], j, digitalRead(_misoPin));
            // Set Clock LOW.
            digitalWrite(_sckPin, LOW);
          }
        }
        digitalWrite(_csPin, HIGH);
      }

      // Here we take the second two bytes returned as our value.
      // This value is already correctly aligned since we are using the 8-bit
      // segments approach. The BIT_MASK is calculated based on the number out
      // bits specified in the template parameters.
      return ((data[SPI_TRANSFER_LEGNTH - 2] << 8) | data[SPI_TRANSFER_LEGNTH - 1]) & BIT_MASK;
    }


    /// \brief Use hardware SPI to communicate.
    bool _useHardwareSPI = true;

    /// \brief Chip Select pin.
    uint8_t _csPin = SS;

    /// \brief MOSI pin.
    uint8_t _mosiPin = MOSI;

    /// \brief MISO pin.
    uint8_t _misoPin = MISO;

    /// \brief SCLK pin.
    uint8_t _sckPin = SCK;

};

/// \brief A typedef for the MCP3002.
/// Max clock frequency for 2.7V: 1200000 Hz
/// Max clock frequency for 5.0V: 3200000 Hz
/// \sa http://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf
typedef MCP3XXX_<10, 2, 1200000, 2> MCP3002;

/// \brief A typedef for the MCP3004.
/// Max clock frequency for 2.7V: 1350000 Hz
/// Max clock frequency for 5.0V: 3600000 Hz
/// \sa http://ww1.microchip.com/downloads/en/DeviceDoc/21295C.pdf
typedef MCP3XXX_<10, 4, 1350000> MCP3004;

/// \brief A typedef for the MCP3008.
/// Max clock frequency for 2.7V: 1350000 Hz
/// Max clock frequency for 5.0V: 3600000 Hz
/// \sa http://ww1.microchip.com/downloads/en/DeviceDoc/21295C.pdf
//typedef MCP3XXX_<10, 8, 1350000> MCP3008;
typedef MCP3XXX_<10, 8, 3000000> MCP3008;

// /// \brief A typedef for the MCP3202.
// /// Max clock frequency for 2.7V:  900000 Hz
// /// Max clock frequency for 5.0V: 1800000 Hz
// /// \sa http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf
// typedef MCP3XXX_<12, 2, 900000> MCP3202;
//
// /// \brief A typedef for the MCP3204.
// /// Max clock frequency for 2.7V: 1000000 Hz
// /// Max clock frequency for 5.0V: 2000000 Hz
// /// \sa http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf
// typedef MCP3XXX_<12, 4, 1000000> MCP3204;
//
// /// \brief A typedef for the MCP3208.
// /// Max clock frequency for 2.7V: 1000000 Hz
// /// Max clock frequency for 5.0V: 2000000 Hz
// /// \sa http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf
// typedef MCP3XXX_<12, 8, 1000000> MCP3208;
//
// /// \brief A typedef for the MCP3208.
// /// Max clock frequency for 2.7V: 1050000 Hz
// /// Max clock frequency for 5.0V: 2100000 Hz
// /// \sa http://ww1.microchip.com/downloads/en/DeviceDoc/21697e.pdf
// typedef MCP3XXX_<13, 8, 1050000> MCP3304;

Hasil pengukuran perioda sebagai berikut

start
durasi (ms) 0.0137
durasi (ms) 0.0132
durasi (ms) 0.0132
durasi (ms) 0.0132

Output osiloskop

Pengukuran kecepatan konversi ADC MCP3008 pada ESP32 Devkit C clone
Output osiloskop

Frekuensi sinyal output sama dengan frekuensi konversi ADC , yaitu 75,739 kHz

Kesimpulan

  • Library original menghasilkan frekuensi ADC 26,685 kHz, sedangkan library yang dimodifikasi menghasilkan frekuensi ADC 75,739 kHz
  • Library original menghasilkan perioda ADC 0,0370 ms, sedangkan library yang dimodifikasi menghasilkan perioda 0,0132 ms

Referensi

Pengukuran Kecepatan ADC Internal ESP32

Pengukuran Kecepatan ADC Internal ESP32

int counter;  // how many iterations
int time_begin = 0;
int time_end = 0;
int duration;
const int PIN_OUTPUT = 19;
int sensorPin = 34;  // select the input pin for the potentiometer

void setup() {
  Serial.begin(115200);
  counter = 0;
  pinMode(PIN_OUTPUT, OUTPUT);
  Serial.println("start benchmark");
}
//---------------------------------------------------
void loop() {
  int data = 0;
  int value;  // angka yang ditulis
  value = 0;  // minimum value

  data = analogRead(sensorPin);
  //  Serial.println(data);
  //  delay(1000);
  digitalWrite(PIN_OUTPUT, HIGH);

  data = analogRead(sensorPin);
  //Serial.println(data);
  //delay(1000);
  digitalWrite(PIN_OUTPUT, LOW);

  counter = counter + 1;
  if (counter >= 10000) {
    float period;
    int time_now = millis();
    counter = 0;
    duration = time_now - time_begin;
    period = duration / 10000.0 / 2;
    Serial.print("period (ms): ");
    Serial.println(period);
    //  prepare next round
    time_begin = time_now;
  }
}

Pengukuran

Pengukuran perioda

start benchmark
period (ms): 0.09
period (ms): 0.09
period (ms): 0.09
period (ms): 0.09

Pengukuran pin output

Kesimpulan

Perioda ADC adalah 0.09 ms

Frekuensi ADC adalah 10,742 kHz

Referensi

Frekuensi DAC MCP4725 pada ESP32 C3

Pengukuran Frekuensi DAC MCP4725 pada ESP32

Foto perangkat

Kode Pengujian


#include <Wire.h>
#include <Adafruit_MCP4725.h>
#include <Wire.h>

#define I2C_SDA 15
#define I2C_SCL 13

Adafruit_MCP4725 dac;

void setup(void) {
  int address = 0;
  int hasil;
  uint32_t speed = 400000L;
  int status;
  status = Wire.begin(I2C_SDA, I2C_SCL, speed);
  Serial.begin(115200);
  Serial.print("Hello! Wire Init status:");
  Serial.println(status);
  Serial.println(speed);

  address = 0x62;
  dac.begin(address);
  Serial.println("Search I2C");
  SearchI2C();
  Serial.println("benchmark");
}
int start_sawtooth = 0;
int current_time;
int duration;
int time_begin;
int time_now;
uint32_t counter;
void loop(void) {
  dac.setVoltage(0, false);
  dac.setVoltage(4095, false);
  counter = counter + 1;
  if (counter >= 10000) {
    float period;
    int time_now = millis();
    counter = 0;
    duration = time_now - time_begin;
    period = duration / 10000.0 / 2;
    Serial.print("period (ms): ");
    Serial.println(period);
    //  prepare next round
    time_begin = time_now;
  }
}

void SearchI2C() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for (address = 1; address < 127; address++) {
    //    Serial.println(address, HEX);
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.print(address, HEX);
      Serial.println("  !");

      nDevices++;
    } else if (error == 4) {
      Serial.print("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
}

Pengukuran

Hasil pengukuran perioda

benchmark
period (ms): 0.18
period (ms): 0.17
period (ms): 0.17

Hasil pengukuran sinyal output DAC

Frekuensi DAC adalah 2,867 kHz x 2 = 5,734 kHz

Kesimpulan

Perioda : 0.17 ms

Frekuensi: 5,734 kHz

Referensi

Pengukuran Frekuensi ADC ESP32 C3

Pengukuran frekuensi ADC internal pada modul ESP32-C3-Core (Luatos)

Berikut ini rangkaian untuk pengujian

Berikut ini kode yang dipakai untuk pengukuran

int counter;  // how many iterations
int time_begin = 0;
int time_end = 0;
int duration;
const int PIN_OUTPUT = 1;
int sensorPin = 0;  // select the input pin for the potentiometer

void setup() {
  Serial.begin(115200);
  counter = 0;
  pinMode(PIN_OUTPUT, OUTPUT);
  Serial.println("start benchmark");
}
//---------------------------------------------------
void loop() {
  int data = 0;
  int value;  // angka yang ditulis
  value = 0;  // minimum value

  data = analogRead(sensorPin);
  //  Serial.println(data);
  //  delay(1000);
  digitalWrite(PIN_OUTPUT, HIGH);

  data = analogRead(sensorPin);
  //Serial.println(data);
  //delay(1000);
  digitalWrite(PIN_OUTPUT, LOW);

  counter = counter + 1;
  if (counter >= 10000) {
    float period;
    int time_now = millis();
    counter = 0;
    duration = time_now - time_begin;
    period = duration / 10000.0 / 2;
    Serial.print("period (ms): ");
    Serial.println(period);
    //  prepare next round
    time_begin = time_now;
  }
}

Berikut ini hasil pengukuran perioda di port serial

start benchmark
period (ms): 0.06
period (ms): 0.06
period (ms): 0.06

Berikut ini hasil pengukuran frekuensi sinyal di pin 1

Kesimpulan

frekuensi ADC adalah 17,288 kHz

perioda ADC adalah 0,06 ms