Apa Itu Mikrokontroler dan Contohnya

Apa yang dimaksud dengan mikrokontroler?

Jawab: Pengertian mikrokontroler adalah suatu komputer kecil dalam satu keping rangkaian terintegrasi. Suatu mikrokontroler di dalamnya terdiri dari satu atau lebih CPU (Central Processing Unit / Unit pengolahan terpusat) dengan sejumlah memori dan periferal input/output.

Mengapa mikrokontroler disebut sebagai komputer?

Jawab: Mikrokontroler disebut sebagai komputer karena memang mikrokontroler adalah suatu komputer lengkap. Perbedaan khusus dibandingkan komputer biasa adalah semua komponen komputer pada mikrokontroler sudah terkandung dalam satu rangkaian terintegrasi, sedangkan pada komputer biasa komponen-komponen tersebut berada pada beberapa keping rangkaian terintegrasi.

Sebagai contoh,  Arduino UNO / Nano di dalamnya ada komponen utama mikrokontroler tipe ATmega328 . Di dalam ATmega328 ini sudah ada CPU, memori flash untuk menampung program, memori RAM (Random Access Memory) untuk menampung variabel di perangkat lunak, dan EEPROM (Electrically Erasable Programmable Read Only Memory) untuk menampung data yang dapat diubah oleh program namun tidak hilang kalau listrik dimatikan.

Berikut ini foto ATmega328

Sebagai perbandingan , motherboard komputer desktop memiliki CPU, memori dan periferal masing-masing pada rangkaian terintegrasi yang terpisah. Berikut ini contoh papan rangkaian motherboard.

 

Berikut ini contoh CPU AMD Ryzen 9 5950X. Dalam rangkaian terintegrasi ini hanya ada CPU saja, belum dilengkapi dengan RAM maupun periferal lain.

Referensi

  • https://en.wikipedia.org/wiki/Motherboard

Kenapa mikrokontroler sering disebut juga sebagai komputer mini?

Mikrokontroler sering disebut juga sebagai komputer mini karena mikrokontroler sudah merupakan satu komputer lengkap yang dapat menjalankan perangkat lunak, dan ukurannya kecil (maka disebut sebagai mini).

Istilah ‘minicomputer’ sebenarnya pernah dipakai di tahun 1960-an untuk menyebut komputer serba guna yang ada di era itu. Ukurannya cukup besar dibandingkan komputer zaman sekarang.  Lebih jauh dapat dibaca di https://en.wikipedia.org/wiki/Minicomputer

Apakah mikrokontroler termasuk ke dalam komputer?

Ya, mikrokontroler termasuk dalam salah satu jenis komputer.

Apa contoh mikrokontroler?

Contoh mikrokontroler di antaranya:

  • ESP32
  • ESP8266
  • ATmega328 yang dipakai di Arduino Nano dan Arduino UNO
  • RP2040 yang dipakai di Arduino Nano RP2040
  • Keluarga STM32 , seperti STM32F103C8T6  yang dipakai di modul Blue Pill
  • nRF52840 yang dipakai di Arduio Nano 33 BLE Sense
  • Atmel SAM3X8E yang dipakai di Arduino Due
  •  

Referensi

  • RP2040 https://en.wikipedia.org/wiki/RP2040
  • ATmega328 https://www.microchip.com/en-us/product/atmega328
  • ESP32 https://en.wikipedia.org/wiki/ESP32
  • STM32 Blue Pill https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill.html

Apa kelebihan mikrokontroler

Keuntungan mikrokontroler dan keistimewaan dibandingkan mikroprosesor biasa adalah:

  • ukuran kecil karena semua komponen komputer sudah ada dalam satu keping chip.
  • penggunaan daya kecil
  • pembuatan perangkat keras / rangkaian lebih mudah karena rangkaian lebih sederhana

Apa kekurangan mikrokontroler?

Kekurangan mikrokontroler adalah terutama pada ukurannya yang kecil, harus muat di dalam satu keping rangkaian terintegrasi. Akibatnya kemampuan komputasinya terbatas, memori terbatas, periferal juga terbatas dibandingkan dengan mikroprosesor.

Kemampuan komputasi terbatas artinya kecepatan komputasi relatif lambat.

Periferal terbatas, artinya input output digital maupun analog terbatas. Media penyimpanan terbatas. Jika perlu penyimpanan tambahan, biasanya  untuk mikrokontroler menggunakan memori tipe SD card. Mikroprosesor dapat menggunakan media besar seperti flashdisk, SSD dan hard disk.

Mikrokontroler pakai bahasa apa?

Mikrokontroler yang ada saat ini umumnya diprogram menggunakan bahasa pemrograman Assembly, C dan C++. Bahasa lain jarang dipakai, misalkan sebagai berikut:

  • Python dipakai di NodeMCU dengan bahasa MicroPython (https://micropython.org/)
  • Rust dipakai untuk ESP32 https://github.com/esp-rs/awesome-esp-rust
  • TinyGo (versi kecil dari Go) https://tinygo.org/

Apa singkatan dari mikrokontroler?

Mikrokontroler sering disingkat sebagai MCU  (Microcontroller Unit)

Apa fungsi ALU dalam mikrokontroler?

ALU (Arithmetic & Logic Unit) adalah bagian dari CPU (Central Processing Unit), sedangkan CPU adalah bagian dari mikrokontroler. Fungsi ALU pada mikrokontroler sama seperti fungsi ALU pada CPU, yaitu untuk melakukan proses perhitungan aritmatik (tambah kurang kali bagi) dan logika (AND, OR, NOT, penggeseran bit)

Apa bagian dari mikrokontroler?

Bagian-bagian utama dari mikrokontroler adalah: CPU, memori dan periferal.

  • CPU (Central Processing Unit) berfungsi mengatur seluruh aktivitas di dalam mikrokontroler
  • Memori berfungsi untuk menyimpan program dan variabel-variabel.
  • Periferal berfungsi menghubungkan mikrokontroler ke dunia luar

Sebagai contoh, berikut ini blok diagram mikrokontroler ESP32

Blok diagram ESP32
Blok diagram ESP32

Penjelasan:

  • CPU pada ESP32 tersebut adalah “Xtensa LX6 microprocessor”
    Memori adalah ROM dan SRAM
  • Periferal adalah bagian-bagian lainnya, seperti Radio, Cryptographic, Peripheral Interfaces (I2C, SDIO, CAN, IR, Temperature Sensor, DAC, SPI, I2S, UART, ETH, PWM, Touch Sensor, SAR ADC)

Apa fungsi chip pada mikrokontroler?

Apakah Chip termasuk mikrokontroler?

Chip tidak termasuk mikrokontroler. Justru mikrokontroler adalah salah satu jenis chip. Chip jenis lain selain mikrokontroler banyak , misal chip penguat op-amp, chip rangkaian logika dan sebagainya.

Apa yang dimaksud dengan sistem minimum mikrokontroler?

Mikrokontroler secara definisi sudah dapat langsung dijalankan tanpa tambahan komponen mikroprosesor lain, jadi istilah ‘sistem minimum mikrokontroler’ ini agak rancu. Beberapa mikrokontroler sudah dapat dijalankan hanya dengan menambahkan tegangan power supply, namun ada juga beberapa mikrokontroler yang masih memerlukan tambahan komponen seperti kristal untuk clock.

Istilah ‘sistem minimum mikroprosesor’ sebenarnya dikenal untuk mikroprosesor, yaitu rangkaian minimum suatu sistem mikroprosesor (CPU, RAM dan periferal) yang dapat menjalankan suatu program sederhana.

Apa karakteristik mikrokontroler?

Karakteristik utama mikrokontroler adalah sebagai berikut

  • mikrokontroler adalah komputer, di dalamnya ada CPU , memori dan periferal
  • sering dipakai untuk mengendalikan perangkat-perangkat kecil
  • dipakai di sistem tertanam (embedded systems), yaitu perangkat yang di dalamnya terdapat komputer namun komputer tersebut tidak kelihatan
  • kemampuan komputasi terbatas, jadi umumnya hanya dipakai untuk komputasi ringan
  • konsumsi daya mikrokontroler relatif kecil dibandingkan mikroprosesor biasa. terutama di perangkat yang mobile/mudah dipindahkan.
  • Sering dipakai untuk menangani pekerjaan waktu nyata (pekerjaan yang memiliki batas waktu ketat)
  • Sudah dilengkapi dengan periferal input & output jadi dapat langsung disambung ke sensor dan aktuator
  • program pada mikrokontroler umumnya disimpan di flash memory, bukan di hard drive ataupun SSD
  • harga relatif murah
  • ukuran kecil, mudah diintegrasikan dengan produk lain
  • Ukuran memori dan periferal pada mikrokontroler tidak dapat diubah, sehingga mikrokontroler diproduksi dengan berbagai kombinasi kemampuan memori dan periferal. Mikroprosesor dapat dikonfigurasi kemampuannya dengan menambah periferal, jadi jenis mikroprosesor tidak terlalu banyak.

 

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:

 

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

Frekuensi DAC MCP4725 pada ESP32 C3

Pada percobaan ini diukur frekuensi & perioda konversi DAC tipe MCP4725 pada modul ESP32 C3 Luatos.

Rangkaian yang diuji

 

Kode Program

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

#define I2C_SDA 2
#define I2C_SCL 3

Adafruit_MCP4725 dac;

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

  address = 0x60;
  dac.begin(address);
  Serial.println("Search I2C");
  SearchI2C();
  Serial.println("Generating a triangle wave");
}
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");
}

Kode ada di https://github.com/waskita/embedded/tree/master/esp32-c3-mcp4725

Pengukuran

Pengukuran dilakukan dengan frekuensi clock I2C dari 100 kHz sampai 3 Mhz. Semua menghasilkan angka yang sama.

Sinyal keluaran MCP4725 diukur dengan osiloskop.

Didapat frekuensi sinyal output adalah 3,080 kHz. Jadi frekuensi update DAC adalah 6,16 kHz

period (ms): 0.17
period (ms): 0.16
period (ms): 0.16
period (ms): 0.16

Pengukuran perioda menghasilkan angka 0,16 ms

Kesimpulan

Frekuensi update DAC adalah 6,16 kHz

Perioda 0,16 ms

Referensi

Perancangan dan Implementasi Low Pass Filter Digital Dengan ESP32

Perancangan Filter

Perancangan filter menggunakan tools dari https://fiiir.com/

Parameter yang digunakan:

  • Sampling rate: 20000 Hz
  • Cut off frequency 800 Hz
  • Transition bandwidth 1800 Hz
  • Window type : Blackman

Berikut ini karakteristik filter yang dapat dilihat di laman yang sama

Kode dalam bahasa Python untuk menghitung parameter filter dan konvolusinya juga dihasilkan dari laman yang sama, sebagai berikut:

from __future__ import print_function
from __future__ import division

import numpy as np

# Example code, computes the coefficients of a low-pass windowed-sinc filter.

# Configuration.
fS = 20000 # Sampling rate.
fL = 800 # Cutoff frequency.
N = 53 # Filter length, must be odd.

# Compute sinc filter.
h = np.sinc(2 * fL / fS * (np.arange(N) - (N - 1) / 2))

# Apply window.
h *= np.blackman(N)

# Normalize to get unity gain.
h /= np.sum(h)

print(h)

# Applying the filter to a signal s can be as simple as writing
# s = np.convolve(s, h)

Parameter filter yang dihasilkan adalah sebagai berikut  (sebagai Python array)

[-4.29317419e-20 -4.18549678e-21 -1.79819385e-05 -8.38178513e-05
 -2.28616892e-04 -4.79528638e-04 -8.51847897e-04 -1.33864303e-03
 -1.89910369e-03 -2.44776137e-03 -2.84740649e-03 -2.90866942e-03
 -2.39870072e-03 -1.06016948e-03  1.35995551e-03  5.07437980e-03
  1.02166209e-02  1.68050560e-02  2.47160945e-02  3.36720917e-02
  4.32479500e-02  5.28978134e-02  6.20002342e-02  6.99171799e-02
  7.60597872e-02  7.99523091e-02  8.12855501e-02  7.99523091e-02
  7.60597872e-02  6.99171799e-02  6.20002342e-02  5.28978134e-02
  4.32479500e-02  3.36720917e-02  2.47160945e-02  1.68050560e-02
  1.02166209e-02  5.07437980e-03  1.35995551e-03 -1.06016948e-03
 -2.39870072e-03 -2.90866942e-03 -2.84740649e-03 -2.44776137e-03
 -1.89910369e-03 -1.33864303e-03 -8.51847897e-04 -4.79528638e-04
 -2.28616892e-04 -8.38178513e-05 -1.79819385e-05 -4.18549678e-21
 -4.29317419e-20]

Simulasi dengan Python di Desktop

Berikut ini kode untuk simulasi filter tersebut di Jupyter Notebook dengan bahasa Python.

from __future__ import print_function
from __future__ import division

import numpy as np
import math
import matplotlib.pyplot as plt

# Example code, computes the coefficients of a low-pass windowed-sinc filter.

# Configuration.
fS = 20000 # Sampling rate.
fL = 800 # Cutoff frequency.
N = 53 # Filter length, must be odd.

# Compute sinc filter.
h = np.sinc(2 * fL / fS * (np.arange(N) - (N - 1) / 2))

# Apply window.
h *= np.blackman(N)

# Normalize to get unity gain.
h /= np.sum(h)

print(h)

# Applying the filter to a signal s can be as simple as writing
# s = np.convolve(s, h)

x = np.linspace(0,1, 20001)

# filter digital
signal_frequency=8000 # diubah-ubah sesuai keperluan
y=np.sin(x*2*math.pi * signal_frequency)
# Applying the filter to a signal s can be as simple as writing
y_out = np.convolve(y, h)
plt.figure(figsize=(16,6))
plt.plot(x, y_out[0:20001],label="output")
plt.plot(x, y[0:20001],label="input")
plt.title("signal:{} Hz".format(signal_frequency))
plt.legend()
plt.axis('tight')
plt.xlim([0, 0.01])
plt.savefig("simulasi-signal-{}.jpg".format(signal_frequency))

Hasil simulasi untuk frekuensi 8 Hz

Hasil simulasi untuk frekuensi 80 HzHasil simulasi untuk frekuensi 800 Hz

Hasil simulasi untuk frekuensi 8000 Hz

Simulasi dengan C di Desktop

Pada percobaan ini filter disimulasikan di Desktop PC untuk mengecek ketepatan perhitungan dibandingkan dengan versi Python.

Kode untuk simulasi C sebagai berikut:

#include <stdio.h>
#include <stdlib.h>
#include "math.h"

int main()
{

#define ORDE_FILTER 53
int i,j,k;
FILE * fp;
char filename[100];
printf("Hello world!\n");
// simulasi 1 detik saja

float signal_frequency=8; // frekuensi input signal
float filter_coefficients[]= {-4.29317419e-20, -4.18549678e-21, -1.79819385e-05, -8.38178513e-05,
-2.28616892e-04, -4.79528638e-04, -8.51847897e-04, -1.33864303e-03,
-1.89910369e-03, -2.44776137e-03, -2.84740649e-03, -2.90866942e-03,
-2.39870072e-03, -1.06016948e-03, 1.35995551e-03, 5.07437980e-03,
1.02166209e-02, 1.68050560e-02, 2.47160945e-02, 3.36720917e-02,
4.32479500e-02, 5.28978134e-02, 6.20002342e-02, 6.99171799e-02,
7.60597872e-02, 7.99523091e-02, 8.12855501e-02, 7.99523091e-02,
7.60597872e-02, 6.99171799e-02, 6.20002342e-02, 5.28978134e-02,
4.32479500e-02, 3.36720917e-02, 2.47160945e-02, 1.68050560e-02,
1.02166209e-02, 5.07437980e-03, 1.35995551e-03, -1.06016948e-03,
-2.39870072e-03, -2.90866942e-03, -2.84740649e-03, -2.44776137e-03,
-1.89910369e-03, -1.33864303e-03, -8.51847897e-04, -4.79528638e-04,
-2.28616892e-04, -8.38178513e-05, -1.79819385e-05, -4.18549678e-21,
-4.29317419e-20
};
int orde_filter=ORDE_FILTER;
float y_history[ORDE_FILTER];
signal_frequency=8000;
sprintf(filename,"simulasi-%d.csv",(int)signal_frequency);
fp = fopen (filename, "w");
fprintf(fp,"time,y,y_out\n");

// zeros y_history
for (i=0; i<orde_filter; i++)
{
y_history[i]=0;
}
for (i=0; i<20000; i++)
{
printf(".");
float t,y;
t=(float)i/(float)20000; // time axis
y=sin(2 * M_PI *signal_frequency* t);
// fprintf(fp,"%f,%f\n",t,y);

// hitung history signal
for (j=orde_filter-1; j>=1; j--)
{
int src=j-1;
int dst=j;
y_history[dst]=y_history[src];
// printf("%d %d\n",src,dst);
}
y_history[0]=y;

// hitung konvolusi
float y_out=0;
for (k=0; k<orde_filter; k++)
{
// fprintf(fp,"%5.3f ",y_history[k]);
y_out=y_out+y_history[k]*filter_coefficients[k];
}
// fprintf(fp,"\n");
fprintf(fp,"%f,%f,%f\n",t,y,y_out);
}
fclose(fp);
return 0;
}



// https://www.tutorialspoint.com/c_standard_library/c_function_fprintf.htm

Output kode C tersebut berupa file *.csv

Visualisasi data di file *.csv dilakukan menggunakan Jupyter Notebook dengan kode sebagai berikut:

import pandas as pd
import math
import matplotlib.pyplot as plt

name="simulasi-8"
name="simulasi-80"
name="simulasi-800"
name="simulasi-8000"
df = pd.read_csv('../filter-simulasi-c/{}.csv'.format(name))

plt.figure(figsize=(16,6))
plt.plot(df["time"], df["y"],marker='o',label="input")
plt.plot(df["time"], df["y_out"],marker='o',label="output")
plt.legend()
plt.axis('tight')
plt.xlim([0, 0.001])
plt.savefig("visualisasi-{}.jpg".format(name))

Tampilan Visualisasi untuk sinyal 8 Hz

nampak sinyal 8 Hz tidak teredam

Tampilan Visualisasi untuk sinyal 80 Hz

sinyal 80 Hz nampak teredam sedikit sekali dan ada lag

Tampilan Visualisasi untuk sinyal 800 Hz

nampak sinyal 800 Hz teredam sekitar 50%

Tampilan Visualisasi untuk sinyal 8000 Hz

nampak sinyal 8000 Hz teredam hampir semuanya

Simulasi dengan C di ESP32

pada percobaan ini kode dijalankan di ESP32 namun input adalah simulasi bukan dari generator sinyal. Output direkam ke port serial, bukan ke osiloskop.

Kode ESP32 adalah sebagai berikut

#define ORDE_FILTER 53

void setup() {

  Serial.begin(115200);

  //

  int i, j, k;

  char filename[100];

  // simulasi 1 detik saja

  float signal_frequency = 8;  // frekuensi input signal

  float filter_coefficients[] = { -4.29317419e-20, -4.18549678e-21, -1.79819385e-05, -8.38178513e-05,

                                  -2.28616892e-04, -4.79528638e-04, -8.51847897e-04, -1.33864303e-03,

                                  -1.89910369e-03, -2.44776137e-03, -2.84740649e-03, -2.90866942e-03,

                                  -2.39870072e-03, -1.06016948e-03, 1.35995551e-03, 5.07437980e-03,

                                  1.02166209e-02, 1.68050560e-02, 2.47160945e-02, 3.36720917e-02,

                                  4.32479500e-02, 5.28978134e-02, 6.20002342e-02, 6.99171799e-02,

                                  7.60597872e-02, 7.99523091e-02, 8.12855501e-02, 7.99523091e-02,

                                  7.60597872e-02, 6.99171799e-02, 6.20002342e-02, 5.28978134e-02,

                                  4.32479500e-02, 3.36720917e-02, 2.47160945e-02, 1.68050560e-02,

                                  1.02166209e-02, 5.07437980e-03, 1.35995551e-03, -1.06016948e-03,

                                  -2.39870072e-03, -2.90866942e-03, -2.84740649e-03, -2.44776137e-03,

                                  -1.89910369e-03, -1.33864303e-03, -8.51847897e-04, -4.79528638e-04,

                                  -2.28616892e-04, -8.38178513e-05, -1.79819385e-05, -4.18549678e-21,

                                  -4.29317419e-20 };

  int orde_filter = ORDE_FILTER;

  float y_history[ORDE_FILTER];

  signal_frequency = 800;

//  signal_frequency = 80;

//  signal_frequency = 8;

  sprintf(filename, "simulasi-%d.csv", (int)signal_frequency);

  printf("time,y,y_out\n");

  // zeros y_history

  for (i = 0; i < orde_filter; i++) {

    y_history[i] = 0;

  }

  for (i = 0; i < 20000; i++) {

    float t, y;

    t = (float)i / (float)20000;  //  time axis

    y = sin(2 * M_PI * signal_frequency * t);

    //        fprintf(fp,"%f,%f\n",t,y);

    // hitung history signal

    for (j = orde_filter - 1; j >= 1; j--) {

      int src = j - 1;

      int dst = j;

      y_history[dst] = y_history[src];

      //            printf("%d %d\n",src,dst);

    }
  y_history[0] = y;
    // hitung konvolusi
    float y_out = 0;
    for (k = 0; k < orde_filter; k++) {
      y_out = y_out + y_history[k] * filter_coefficients[k];
    }

    //        fprintf(fp,"\n");

    printf("%f,%f,%f\n", t, y, y_out);

  }

}

void loop() {

  // put your main code here, to run repeatedly:

}

Output dari ESP32 direkam dengan software RealTerm ke sebuah file *.txt

File *.txt tersebut dirapikan dan disimpan sebagai *.csv

File *.csv ini kemudian divisualisasikan dengan Jupyter Notebook

Kode visualisasi sebagai berikut

# graph simulasi C filter
import pandas as pd
import math
import matplotlib.pyplot as plt

name="esp32-8.csv"
name="esp32-80.csv"
#name="esp32-800.csv"
#name="esp32-8000.csv"
df = pd.read_csv('{}'.format(name))

plt.figure(figsize=(16,6))
plt.plot(df["time"], df["y"],label="input")
plt.plot(df["time"], df["y_out"],label="output")
plt.legend()
plt.axis('tight')
plt.xlim([0, 0.1])
plt.title(name)
plt.savefig("visualisasi-{}.jpg".format(name))

Sinyal 8 Hz:

Sinyal 80 Hz

Sinyal 800 Hz

Sinyal 8000 Hz

Kesimpulan: output dari software LPF di ESP32 sama dengan output dari software C di Desktop

Profiling di ESP32

Pada percobaan ini waktu yang diperlukan untuk menghitung filter diukur di ESP32.

Pewaktuan menggunakan fungsi millis(). Fungsi millis() tidak 100% akurat. Untuk lebih tepat perlu interupsi timer, atau dengan osiloskop.

Kode profiling:

#define ORDE_FILTER 53
float buffer[100];
void setup() {
  int buffer_index = 0;
  int durasi;
  Serial.begin(115200);
  //
  long int i;
  int j, k;
  char filename[100];
  // simulasi 1 detik saja

  float signal_frequency = 8;  // frekuensi input signal
  float filter_coefficients[] = { -4.29317419e-20, -4.18549678e-21, -1.79819385e-05, -8.38178513e-05,
                                  -2.28616892e-04, -4.79528638e-04, -8.51847897e-04, -1.33864303e-03,
                                  -1.89910369e-03, -2.44776137e-03, -2.84740649e-03, -2.90866942e-03,
                                  -2.39870072e-03, -1.06016948e-03, 1.35995551e-03, 5.07437980e-03,
                                  1.02166209e-02, 1.68050560e-02, 2.47160945e-02, 3.36720917e-02,
                                  4.32479500e-02, 5.28978134e-02, 6.20002342e-02, 6.99171799e-02,
                                  7.60597872e-02, 7.99523091e-02, 8.12855501e-02, 7.99523091e-02,
                                  7.60597872e-02, 6.99171799e-02, 6.20002342e-02, 5.28978134e-02,
                                  4.32479500e-02, 3.36720917e-02, 2.47160945e-02, 1.68050560e-02,
                                  1.02166209e-02, 5.07437980e-03, 1.35995551e-03, -1.06016948e-03,
                                  -2.39870072e-03, -2.90866942e-03, -2.84740649e-03, -2.44776137e-03,
                                  -1.89910369e-03, -1.33864303e-03, -8.51847897e-04, -4.79528638e-04,
                                  -2.28616892e-04, -8.38178513e-05, -1.79819385e-05, -4.18549678e-21,
                                  -4.29317419e-20 };
  int orde_filter = ORDE_FILTER;
  float y_history[ORDE_FILTER];
  signal_frequency = 800;
  //  signal_frequency = 80;
  //  signal_frequency = 8;
  printf(“time,y,y_out\n”);

  // zeros y_history
  for (i = 0; i < orde_filter; i++) {
    y_history[i] = 0;
  }
  int time_start = millis();

  for (i = 0; i < 1000000L; i++) {
    float t, y;
    t = (float)i / (float)20000;  //  time axis
    y = sin(2 * M_PI * signal_frequency * t);
    //        fprintf(fp,”%f,%f\n”,t,y);

    // hitung history signal
    for (j = orde_filter – 1; j >= 1; j–) {
      int src = j – 1;
      int dst = j;
      y_history[dst] = y_history[src];
      //            printf(“%d %d\n”,src,dst);
    }
    y_history[0] = y;

    // hitung konvolusi
    float y_out = 0;
    for (k = 0; k < orde_filter; k++) {
      y_out = y_out + y_history[k] * filter_coefficients[k];
    }
    //        fprintf(fp,”\n”);
    //    Serial.print(“.”);
    buffer[buffer_index] = y_out;
    buffer_index++;
    if (buffer_index>100){
      buffer_index=0;
    }
  }
  int time_end = millis();
  durasi = time_end – time_start;
  Serial.println(“durasi”);
  Serial.println(durasi);
}

void loop() {
  // put your main code here, to run repeatedly:
}

Hasil profiling: kode memerlukan 16479 ms untuk menjalankan 1000000 kali perhitungan. jadi setiap perhitungan memerlukan 16.479 us

Konversi DAC di ESP32 memerlukan sekitar 20 us (pesimis), jadi jika kode sekuensial maka didapatkan perioda 36.479 us, atau frekuensi = 27413 Hz.

Frekuensi filter yang dirancang adalah 20000 Hz, jadi masih di bawah batas 27413 Hz.

Pengujian Dengan Sinyal Sesungguhnya

Pada percobaan ini kode dijalankan di ESP32 dengan input dari generator sinyal dan output diamati di osiloskop

Berikut ini implementasi rangkaian:

Implementasi filter digital dengan ESP32, MCP3008 dan level converter
Implementasi filter digital dengan ESP32, MCP3008 dan level converter

Implementasi software dapat dilihat di https://github.com/waskita/embedded/tree/master/esp32_mcp3008_baker_adc_dac_filter-timer

Sinual input didapat dari  generator sinyal GW Instek AFG-2012

Pengukuran output menggunakan osiloskop GW Instek-1152A-U

Berikut ini pengukuran pada frekuensi cut off = 100 Hz jauh di bawah frekuensi cut off.

Berikut ini pengukuran pada frekuensi cut off = 800 Hz. Amplitudo sinyal output sekitar 50% sinyal input.

Berikut ini pengukuran pada frekuensi 1600 Hz, jauh di atas cut off. Amplitudo sinyal output kecil sekali hampir tidak ada.

Berikut ini pengukuran pada frekuensi input 19200 Hz. Terjadi aliasing karena pada sistem ini tidak ada filter anti aliasing.

Referensi

Keuntungan FPGA Dibandingkan Mikrokontroler

Keuntungan FPGA (Field Programmable Gate Array) dibandingkan mikrokontroler di antaranya:

  • Kecepatan FPGA lebih tinggi
  • Daya yang dipakai FPGA lebih kecil untuk pekerjaan komputasi yang sama

Berikut ini ilustrasi perbandingan keperluan daya (dalam mW) untuk melakukan benchmark CoreMarks

FPGA vs Arm Cortex-A9 vs Arm Cortex-A53

Gambar diambil dari artikel “Lowest-Power Multi Core RISC-V SoC FPGAs

Berikut ini ilustrasi perbandingan antara fleksibilitas dan unjuk kerja   & efisiensi dari CPU, GPU, FPGA dan ASIC. Gambar diambil dari : https://www.cs.cornell.edu/courses/cs6120/2022sp/blog/chlorophyll/

Berikut ini gambar dari  https://hacarus.com/tech/20201207-amd-acquires-xilinx/

Bahan bacaan

  • https://www.arrow.com/en/research-and-events/articles/fpga-vs-cpu-vs-gpu-vs-microcontroller

 

Jetson TX2 dan Xilinx Zynq di Drone Lancet

Para ahli dari Ukraina membongkar sebuah drone Lancet buatan Rusia yang dipakai untuk menyerang Ukraina. Berikut ini foto-foto komponen-komponen dari dalam drone tersebut.

Salah satu komponen penting yang ditemukan adalah modul Jetson TX2 buatan NVIDIA. Berikut ini perbandingan antara modul Jetson TX2 di drone Lancet (kiri) dan foto Jetson TX2 asli dari website NVIDIA (kanan).

Berikut ini foto-foto lain dari drone Lancet tersebut

Berikut ini foto baterai lithium polymer dengan kapasitas 11300 mAh, tegangan 3,7 volt

Berikut ini foto komponen power supply

Komponen ini sepertinya bagian dari power supply. Nampak ada komponen induktor yang biasa dipakai di switching power supply.

 

 

Berikut ini foto drone yang sudah dibongkar

Komponen berikut ini sepertinya semacam sensor fd

Komponen berikut sepertinya radio atau GPS. Nampak ada konektor analog frekuensi tinggi di bagian bawahnya.

dfd

Berikut ini tampak bawah dari prosesor Zynq buatan Xilinx

Berikut ini modul memori buatan Hynix dari Korea Selatan

Berikut ini prosesor modul Jetson TX2 buatan NVIDIA

 

Kesimpulan: drone Lancet dari Rusia tersebut menggunakan komponen-komponen prosesor buatan Amerika dan Korea

Update

Pembuatan Lancet memerlukan perangkat produksi berikut ini:

Sumber: https://twitter.com/DrGuideTech/status/1686663004530634753

Sumber:

 

Konfigurasi Sistem Mikroprosesor oleh Pengguna

Mikroprosesor/mikrokontroler dapat dipakai untuk membuat sistem mikroprosesor/ sistem embedded / sistem instrumentasi.

Perangkat tersebut seringkali perlu dikonfigurasi sesuai keadaan di tempat pengguna.

Contoh parameter yang perlu diubah oleh pengguna:

  • nama wifi access point untuk perangkat IoT
  • IP address untuk perangkat IoT
  • Parameter kendali untuk pengendali PID (Proportional Integral Derivative)

Konfigurasi dapat dilakukan sebagai berikut:

  • jumper
  • secara hardcoded di source code
  • protokol konfigurasi jaringan seperti DHCP/BOOTP
  • melalui jaringan komputer Wifi / Ethernet
  • mengubah data kartu memori/storage seperti flash disk, SD card, hard drive dsb
  • komunikasi serial RS232/ RS485 USB / Modbus
  • tombol dan display
  • keyboard + monitor pada komputer desktop/laptop

Data konfigurasi dapat disimpan sebagai:

  • kode di source code
  • hardware jumper
  • data di memory card / storage
  • EEPROM

Contoh

  • perangkat IoT merek Sonoff/Bardi, menggunakan WiFi untuk konfigurasi. Bisa langsung login ke IoT tersebut, atau pairing menggunakan aplikasi mobile phone.
  • WiFi access point, rata-rata dikonfigurasi menggunakan web server yang ada di perangkat tersebut
  • Perangkat lunak Tasmota untuk ESP8266, dikonfigurasi melalui WiFi https://tasmota.github.io/docs/
  • Pengendali temperatur REC-C100, dikonfigurasi menggunakan tombol dan display LED https://elektrologi.iptek.web.id/pengendali-temperatur-rex-c100
  • Kendali pintu otomatis , dikonfigurasi melalui port serial. Contoh: https://support.industry.siemens.com/cs/document/101978636/sidoor-ate500e-system-manual?dti=0&lc=en-CH
  •  

Konfigurasi Dengan Sakelar atau Jumper

Berikut ini beberapa contoh sakelar yang dapat dipakai sebagai konfigurasi.

Berikut ini sakelar dengan bentuk DIP (Dual Inline Package) dengan 2 state (ON  dan OFF)

Berikut ini contoh sakelar dengan 3 state.

Berikut ini sakelar dengan bentuk rotary switch.

Berikut ini header dan jumper untuk konfigurasi

Jumper ada main board sebuah komputer desktop
Jumper pada main board sebuah komputer desktop

Berikut ini berbagai macam bentuk jumper yang umum dipakai

Berbagai macam jumper elektronik
Berbagai macam jumper elektronik

sumber: https://en.wikipedia.org/wiki/Jumper_(computing)

Konfigurasi Dengan Memory Card

Berikut ini contoh memory card micro-SD di Raspberry PI. Konfigurasi sistem dapat disimpan sebagai file di memory card tersebut.

Micro-SD di Raspberry PI
Micro-SD di Raspberry PI

Arduino Nano belum memiliki konektor untuk Micro-SD. Untuk itu perlu ditambah modul micro-SD seperti pada gambar berikut ini.

Modul Micro-SD untuk Arduino
Modul Micro-SD untuk Arduino

Konfigurasi sistem dapat disimpan sebagai file kemudian dapat dibaca dari program aplikasi di Arduino Nano / Arduino UNO.

Tombol dan Display

Berikut ini contoh pengendali temperatur REX-C100 yang menggunakan tombol dan tampilan LED untuk memasukkan konfigurasi temperatur dan berbagai macam parameter sistem kendali.

Parameter kendali disimpan di dalam EEPROM (Electrically Erasable Programmable Read Only Memory) , sehingga tidak hilang ketika listrik dimatikan.

Display pengendali temperatur
Display pengendali temperatur

Web Interface

Access point DIR-612 dari DLink
Access point DIR-612 dari DLink

sumber: https://www.dlink.co.id/product/n300-wireless-fast-ethernet-router/

Berikut ini contoh tampilan konfigurasi Access point DIR-612. Konfigurasi dapat diubah melalui antarmuka web ini dan kemudian disimpan di dalam access point tersebut.

Konfigurasi DIR-612
Konfigurasi DIR-612

Ulasan

  • Konfigurasi jumper cukup makan tempat. perlu pin I/O di mikrokontroler. Jumlah parameter yang dikonfigurasi hanya 1 bit untuk setiap jumper yang dipakai.
  • Konfigurasi secara hardcoded di software mudah dibuat, namun sulit diubah oleh pengguna. Source code juga mesti diakses oleh pengguna, yang hal ini dapat jadi masalah kerahasiaan.
  • Konfigurasi melalui protokol jaringan DHCP praktis untuk melakukan konfigurasi standar jaringan seperti IP address. Untuk konfigurasi yang lebih spesifik, perlu menguasai detail protokol jaringan.
  • Konfigurasi melalui jaringan cocok untuk perangkat yang tersambung ke jaringan komputer melalui WiFi, Ethernet dsb
  • Konfigurasi melalui storage cocok untuk perangkat yang storagenya mudah dilepas & dipasang kembali.
  • Konfigurasi melalui port serial cocok untuk perangkat yang ada port serialnya. kelemahan: perlu komputer dengan port serial untuk mengubah setting.
  • Tombol & display cocok untuk aplikasi industri. Contoh kendali temperatur REX-C100

Referensi

  • https://en.wikipedia.org/wiki/DIP_switch
  • Tasmota https://tasmota.github.io/docs/
  • Tasmota https://tasmota.github.io/docs/Getting-Started/#initial-configuration
  •  

Luatos ESP32-C3-Core

Spesifikasi

  • Based on the ESP32-C3 WIFI & Bluetooth LE RISC-V Single-Core CPU
  • Type-C USB
  • Castellated pads
  • 4MB Flash
  • Clock speed: 160 Mhz
  • 15x Digital IO
  • ADC(5 channel, 12-bit), I2C, SPI, UARTx2
  • Size: 21mm x 51mm
  • Default firmware: LuatOS
  • 2 red status LEDs

Pinout

Deskripsi Pin

Numbering

name

Default function after reset

multiplexing function

power domain

Pull-up and pull-down ability

32

GND

grounding

 

 

 

31

5V

5V power interface, connected to VBUS of USB

 

 

 

30

BOOT

GPIO09, input

BOOTMODE

VDD3P3_CPU

UP/DOWN

29

IO08

GPIO08, input, output, high impedance

 

VDD3P3_CPU

UP/DOWN

28

IO04

GPIO04, input, output, high impedance

I2C_SDA/ADC_4

VDD3P3_RTC

UP/DOWN

27

IO05

GPIO05, input, output, high impedance

I2C_SCL/ADC_5

VDD3P3_RTC

UP/DOWN

26

3.3V

Chip power supply, 3.3V

 

 

 

25

GND

grounding

 

 

 

twenty four

PB_11

GPIO11, input, output, high impedance

VDD_SPI

VDD3P3_CPU

UP/DOWN

twenty three

IO07

GPIO07, input, output, high impedance

SPI2_CS

VDD3P3_CPU

UP/DOWN

twenty two

IO06

GPIO06, input, output, high impedance

 

VDD3P3_CPU

UP/DOWN

twenty one

IO10

GPIO10, input, output, high impedance

SPI2_MISO

VDD3P3_CPU

UP/DOWN

20

IO03

GPIO03, input, output, high impedance

SPI2_MOSI/ADC_3

VDD3P3_RTC

UP/DOWN

19

IO02

GPIO02, input, output, high impedance

SPI2_CK/ADC_2

VDD3P3_CPU

UP/DOWN

18

3.3V

Chip power supply, 3.3V

 

 

 

17

GND

grounding

 

 

 

16

5V

5V power interface, connected to VBUS of USB

 

 

 

15

PWB

Chip 3.3V power supply control, high level is effective, can be suspended when not in use

 

 

 

14

GND

grounding

 

 

 

13

3.3V

Chip power supply, 3.3V

 

 

 

12

RESET

chip reset

 

VDD3P3_RTC

 

11

NC

 

 

 

 

10

IO13

GPIO13, input, output, high impedance

 

VDD3P3_CPU

UP/DOWN

09

U0_RX

GPIO20, input, output, high impedance

UART0_RX

VDD3P3_CPU

UP/DOWN

08

U0_TX

GPIO21, input, output, high impedance

UART0_TX

VDD3P3_CPU

UP/DOWN

07

GND

grounding

 

 

 

06

IO19

GPIO19, input, output, high impedance

USB_D+

VDD3P3_CPU

UP/DOWN

05

IO18

GPIO18, input, output, high impedance

USB_D-

VDD3P3_CPU

UP/DOWN

04

IO12

GPIO12, input, output, high impedance

SPIHD

VDD3P3_CPU

UP/DOWN

03

IO01

GPIO1, input, output, high impedance

UART1_RX/ADC_1

VDD3P3_CPU

UP/DOWN

02

IO00

GPIO0, input, output, high impedance

UART1_TX/ADC_0

VDD3P3_CPU

UP/DOWN

01

GND

grounding

 

 

 

Fungsi

Power Supply

Ada 3 cara memasang power supply:

  • USB-C (default)
  • 5V & GND header
  • 3V3 & GND header

LED

Ada 2 buah LED pada board ini.

LED number

Corresponding to GPIO

pin function

describe

D4

IO12

GPIO12 configuration

active high

D5

IO13

GPIO13 configuration

active high

Tombol

Ada 2 buah tombol, yaitu tombol BOOT dan RST

key number

pin function

describe

BOOT/GPIO9

When the button is pressed, the chip enters the download mode

active low

RST

When the button is pressed, the chip resets

active low

 

Schematic

ESP32 C3 Luatos-schematic flash section
Memori Flash
ESP32 C3 Luatos-schematic mikroprosesor
Skema bagian mikroprosesor
ESP32 C3 Luatos-schematic switch and LEDs
Sakelar dan LEDs
ESP32 C3 Luatos-schematic regulator section
Regulator
ESP32 C3 Luatos-schematic USB section
USB circuit

Teknik Pemrograman

di Arduino IDE, pilih board ESP32C3 Dev Module, kemudian pilih flashmode “DIO”

Tips dari https://github.com/mboehmerm/Luatos_C3_Core_DIO_SSD1309_I2C_128x64

Referensi

 

Tegangan Maksimum pada Raspberry Pi

Berikut ini batas tegangan maksimum yang dapat diberikan pada pin Raspberry Pi

Simbol Parameter Minimum Maksimum Satuan
VBAT Core SMPS Supply -0.5 6.0 volt
3V3 3V3 Supply Voltage -0.5 4.10 volt
1V8 1V8 Supply Voltage -0.5 4.10 volt
VDAC TV DAC Supply -0.5 4.10 volt
GPIO0-27 VDD GPIO0-27 I/O Supply Voltage -0.5 4.10 volt
GPIO28-45 VDD GPIO28-45 I/O Supply Voltage -0.5 4.10 volt
SDX VDD Primary SD/eMMC Supply Voltage -0.5 4.10 volt
         
         

Tabel ini diperoleh dari datasheet Raspberry Pi  https://datasheets.raspberrypi.com/cm/cm1-and-cm3-datasheet.pdf

Modul RISC-V yang kompatibel dengan Ubuntu

RISC-V adalah prosesor yang desainnya dibuat open source. Prosesor ini mulai diperkenalkan tahun 2010. Karena masih baru, belum banyak modul mikroprosesor berbasis RISC-V ini.

Berikut ini daftar modul sistem mikroprosesor dengan prosesor berbasis RISC-V

Galeri

SiFive HiFive Unmatched

 

SiFive Hifive Unmatched
SiFive Hifive Unmatched

Produk ini statusnya sudah sold out

StarFive The VisionFive

StarFive VisionFive

Tersedia di Aliexpress: https://id.aliexpress.com/item/1005003679748239.html

VisionFive sudah sold out, kelanjutannya adalah VisionFive 2

StarFive VisionFive 2
StarFive VisionFive 2

Berikut ini tautan untuk membeli board StarFive Vision Five 2:  

Literatur tentang VisionFive 2

VisonFive 2 Technical Document

  • https://doc-en.rvspace.org/Doc_Center/visionfive_2.html

Applications

  • https://wiki.rvspace.org/en/application/Application
  • https://riscv.or.jp/wp-content/uploads/day3_StarFive_risc-v_tokyo_day2022Autumn.pdf
  • https://rvspace.org/en/project/VisionFive2_Debian_Wiki_202303_Release
  • Hands-on experience with StarFive VisionFive 2 RISC-V SBC using Debian 12 https://www.cnx-software.com/2023/02/12/starfive-visionfive-2-sbc-review-debian-12/
  • VisionFive 2: RISC-V Quad Core Low Cost SBC https://www.youtube.com/watch?v=ykKnc86UtXg
  • RISC-V Business: Testing StarFive’s VisionFive 2 SBC https://www.jeffgeerling.com/blog/2023/risc-v-business-testing-starfives-visionfive-2-sbc
  • StarFiveTech VisionFive2 SDK https://github.com/starfive-tech/VisionFive2
  • StarFive VisionFive 2 (Ubuntu) https://wiki.ubuntu.com/RISC-V/StarFive%20VisionFive%202

AllWinner Nezha

Alwinner Nezha

Tersedia di Aliexpress https://id.aliexpress.com/item/1005003422624354.html

Sipeed LicheeRV Dock

Sipeed LicheeRV Dock

Tersedia di Aliexpress https://www.aliexpress.com/item/1005003741287162.html

Referensi

 

Perbedaan ESP32 dan ESP8266

Perbedaan ESP32 dan ESP8266 adalah sebagai berikut

Parameter ESP32 ESP8266
Prosesor / CPU Xtensa :LX6 dual core / single core Xtensa L:106 single core
clock processor 160 MHz 80 MHz
Memori Flash ada versi dengan built in flash tidak ada built in flash
Memori SRAM    
Memori EEPROM di flash memory  
Wifi HT40 HT20
Bluetooth tidak ada Bluetooth 4.2 dan BLE
SPI 4 2
I2C 2 1
I2S 2 2
UART 2 2
ADC 12 bit 10 bit
CAN ada tidak ada
Built in sensor hall sensor, temperature sensor tidak ada

 

ESP8266 NodeMCU (kiri), ESP32 DevkitC (tengah), ESP32 Lolin32 Lite (kanan)
ESP8266 NodeMCU (kiri), ESP32 DevkitC (tengah), ESP32 Lolin32 Lite (kanan)

Penjelasan Ringkas ESP32

ESP 32 adalah mikrokontroler yang memiliki banyak fitur pada prosesornya, dan dilengkapi dengan konektivitas Wi-Fi dan Bluetooth terintegrasi untuk berbagai macam aplikasi.

ESP32 mampu berfungsi dengan andal di lingkungan industri, dengan suhu pengoperasian mulai dari –40°C hingga +125°C. ESP32 dapat secara dinamis menghilangkan ketidaksempurnaan sirkuit eksternal dan beradaptasi dengan perubahan kondisi eksternal dengan dukungan rangkaian kalibrasi di dalamnya. Rangkaian kalibrasi ini memungkinkan WiFi pada ESP32 berfungsi tanpa perlu kalibrasi ekstra.

ESP32 dirancang untuk perangkat bergerak (mobile), perangkat elektronik yang dapat dikenakan (wearable electronics), dan aplikasi IoT. Konsumsi daya ESP32 dapat dibuat sangat rendah dengan kombinasi beberapa macam perangkat lunak khusus. ESP32 juga mencakup fitur-fitur canggih, seperti ‘clock gating‘ untuk mereduksi konsumsi daya, berbagai mode daya, dan penskalaan daya secara dinamis.

ESP32 dibuat sangat terintegrasi dengan sakelar pemilih antena di dalamnya, RF balun, power amplifier untuk radio, amplifier penerima radio dengan kebisingan rendah (low noise), filter, dan modul manajemen daya. ESP32 menambahkan fungsionalitas dan keserbagunaan yang banyak aplikasi dengan hanya memerlukan ruang kecil di PCB (Printed Circuit Board)

ESP32 dapat berfungsi sebagai sistem mandiri yang lengkap atau sebagai perangkat pembantu ke mikrokontroler lain, mengurangi overhead tumpukan komunikasi pada prosesor aplikasi utama. ESP32 dapat berinteraksi dengan sistem lain untuk menyediakan fungsionalitas Wi-Fi dan Bluetooth melalui antarmuka SPI/SDIO atau I2C/UART.

Modul ESP32 tersedia dalam berbagai versi, di antaranya adalah Lolin32 Lite dan DevkitC serta clone nya.

Penjelasan Ringkas ESP8266

ESP8266 adalah prosesor yang dibuat oleh Espressif. ESP8266 adalah pendahulu dari ESP32.

Referensi