Blog Archive

Arduino Indonesia. Gambar tema oleh Storman. Diberdayakan oleh Blogger.

Supported by Electronics 3 in 1

1. Jasa pencetakan PCB single layer dengan harga paling murah.

(Metode Pembuatan dengan Transfer Toner)
>PCB design sendiri (siap cetak) : Rp.150,-/Cm2
>PCB design dari kami : Rp.250,-/Cm2

(Metode Sablon Full Masking dan Silk Screen minimal pemesanan 100 Pcs)
>PCB design sendiri (siap cetak) : Rp.200,-/Cm2
>PCB design dari kami : Rp.250,-/Cm2

2. Jasa perancangan, perakitan, dan pembuatan trainer pembelajaran elektronika untuk SMK dan Mahasiswa.

3. Jasa perancangan, perakitan, dan pembuatan berbagai macam kontroller, sensor, aktuator, dan tranduser.
>Design Rangkaian / Sistem Elektronika
>Design Rangkaian / Sistem Instrumentasi
>Design Rangkaian / Sistem Kendali
>Kerjasama Riset (data atau peralatan)
>Kerjasama Produksi Produk-Produk KIT Elektronika
>Produksi Instrumentasi Elektronika

4. Jasa Pembuatan Proyek, Tugas Akhir, Tugas Laboratorium, PKM, Karya Ilmiah, SKRIPSI, dll

Like My Facebook

Popular Posts

Kamis, 18 Desember 2025

MicroPython - Mengirim Data Sensor melalui Email menggunakan ESP32/ESP8266 (BME280)

Pada tutorial ini, Anda akan mempelajari cara memprogram board ESP32 dan ESP8266 menggunakan MicroPython untuk mengirimkan data hasil pembacaan sensor ke email. Sebagai contoh, tutorial ini menggunakan sensor BME280 untuk mengirimkan data suhu, kelembapan, dan tekanan udara. Namun, proyek ini dapat dengan mudah dimodifikasi untuk menggunakan jenis sensor lainnya sesuai kebutuhan.

Modul uMail

Untuk mempermudah pengiriman email menggunakan MicroPython, kita akan menggunakan modul bernama uMail. Modul ini tidak termasuk dalam kumpulan pustaka standar MicroPython, sehingga perlu diunggah secara terpisah ke board yang digunakan. Panduan lengkap untuk mengunggah modul tersebut akan dijelaskan pada bagian selanjutnya dalam tutorial ini.

Modul BME280

Untuk membaca data dari sensor BME280, kita akan menggunakan modul tambahan yang tidak termasuk dalam pustaka standar MicroPython secara default. Oleh karena itu, modul ini perlu diunggah terlebih dahulu ke board sebelum mulai menulis kode program. Modul BME280 dapat diunduh melalui tautan yang disediakan.

 

Sebagai panduan awal untuk mempelajari cara menghubungkan dan menggunakan sensor BME280 dengan ESP32/ESP8266 menggunakan MicroPython, Anda dapat merujuk ke tutorial berikut:

- MicroPython: BME280 dengan ESP32 dan ESP8266 (Tekanan, Suhu, dan Kelembaban)

Email Pengirim (Akun Baru)

Disarankan untuk membuat akun email baru yang khusus digunakan sebagai pengirim email ke alamat email pribadi utama Anda. Hindari menggunakan akun email utama untuk mengirim email melalui ESP32 atau ESP8266. Jika terjadi kesalahan pada kode program atau permintaan pengiriman email dilakukan terlalu sering, akun email Anda berisiko diblokir atau dinonaktifkan sementara. Pada tutorial ini, akun Gmail direkomendasikan, namun penyedia layanan email lain pada umumnya juga dapat digunakan.

Membuat App Password

Agar perangkat baru dapat mengirim email melalui akun Gmail, Anda perlu membuat App Password. App Password adalah kode sandi khusus berisi 16 digit yang memberikan izin akses kepada aplikasi atau perangkat dengan tingkat keamanan terbatas untuk menggunakan akun Google Anda. Informasi lebih lanjut mengenai login menggunakan App Password dapat dipelajari pada dokumentasi resmi Google.

 

Silakan ikuti panduan yang tersedia untuk mempelajari langkah-langkah pembuatan App Password.

Jika Anda menggunakan penyedia layanan email selain Gmail, periksa dokumentasi masing-masing penyedia mengenai cara membuat App Password. Biasanya, panduan tersebut dapat ditemukan dengan mudah melalui pencarian Google menggunakan kata kunci: “nama_penyedia_email + create app password”.

Pengkabelan BME280

Pada tutorial ini, kita akan membuat proyek contoh yang mengirimkan data hasil pembacaan sensor BME280 ke email. Oleh karena itu, sensor BME280 perlu dihubungkan terlebih dahulu ke board yang digunakan. Silakan ikuti salah satu diagram skematik pengkabelan berikut.

ESP32 dengan BME280

Komunikasi antara ESP32 dan modul sensor BME280 menggunakan protokol I2C. Hubungkan sensor BME280 ke pin I2C default pada ESP32, yaitu SCL (GPIO 22) dan SDA (GPIO 21), seperti yang ditunjukkan pada diagram skematik berikut.

 


ESP8266 dengan BME280

Komunikasi antara ESP8266 dan modul sensor BME280 menggunakan protokol I2C. Untuk itu, hubungkan sensor BME280 ke pin SDA (GPIO 4) dan SCL (GPIO 5) pada ESP8266, sesuai dengan diagram skematik berikut.

 


Mengunggah Modul uMail

Untuk mengirim email, kita akan menggunakan modul uMail. Anda dapat melihat repositori GitHub modul ini beserta beberapa contoh penggunaannya pada sumber yang tersedia. Perlu diperhatikan bahwa pustaka ini tidak termasuk dalam pustaka standar MicroPython secara default. Oleh karena itu, sebelum digunakan, Anda harus mengunggah file modul uMail ke board ESP32/ESP8266. Simpan file tersebut dengan nama `umail.py` agar dapat dipanggil dengan benar di dalam program.

 

import usocket


DEFAULT_TIMEOUT = 10 # sec

LOCAL_DOMAIN = '127.0.0.1'

CMD_EHLO = 'EHLO'

CMD_STARTTLS = 'STARTTLS'

CMD_AUTH = 'AUTH'

CMD_MAIL = 'MAIL'

AUTH_PLAIN = 'PLAIN'

AUTH_LOGIN = 'LOGIN'


class SMTP:

    def cmd(self, cmd_str):

        sock = self._sock;

        sock.write('%s\r\n' % cmd_str)

        resp = []

        next = True

        while next:

            code = sock.read(3)

            next = sock.read(1) == b'-'

            resp.append(sock.readline().strip().decode())

        return int(code), resp


    def __init__(self, host, port, ssl=False, username=None, password=None):

        import ssl

        self.username = username

        addr = usocket.getaddrinfo(host, port)[0][-1]

        sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)

        sock.settimeout(DEFAULT_TIMEOUT)

        sock.connect(addr)

        if ssl:

            sock = ssl.wrap_socket(sock)

        code = int(sock.read(3))

        sock.readline()

        assert code==220, 'cant connect to server %d, %s' % (code, resp)

        self._sock = sock


        code, resp = self.cmd(CMD_EHLO + ' ' + LOCAL_DOMAIN)

        assert code==250, '%d' % code

        if not ssl and CMD_STARTTLS in resp:

            code, resp = self.cmd(CMD_STARTTLS)

            assert code==220, 'start tls failed %d, %s' % (code, resp)

            self._sock = ssl.wrap_socket(sock)


        if username and password:

            self.login(username, password)


    def login(self, username, password):

        self.username = username

        code, resp = self.cmd(CMD_EHLO + ' ' + LOCAL_DOMAIN)

        assert code==250, '%d, %s' % (code, resp)


        auths = None

        for feature in resp:

            if feature[:4].upper() == CMD_AUTH:

                auths = feature[4:].strip('=').upper().split()

        assert auths!=None, "no auth method"


        from ubinascii import b2a_base64 as b64

        if AUTH_PLAIN in auths:

            cren = b64("\0%s\0%s" % (username, password))[:-1].decode()

            code, resp = self.cmd('%s %s %s' % (CMD_AUTH, AUTH_PLAIN, cren))

        elif AUTH_LOGIN in auths:

            code, resp = self.cmd("%s %s %s" % (CMD_AUTH, AUTH_LOGIN, b64(username)[:-1].decode()))

            assert code==334, 'wrong username %d, %s' % (code, resp)

            code, resp = self.cmd(b64(password)[:-1].decode())

        else:

            raise Exception("auth(%s) not supported " % ', '.join(auths))


        assert code==235 or code==503, 'auth error %d, %s' % (code, resp)

        return code, resp


    def to(self, addrs, mail_from=None):

        mail_from = self.username if mail_from==None else mail_from

        code, resp = self.cmd(CMD_EHLO + ' ' + LOCAL_DOMAIN)

        assert code==250, '%d' % code

        code, resp = self.cmd('MAIL FROM: <%s>' % mail_from)

        assert code==250, 'sender refused %d, %s' % (code, resp)


        if isinstance(addrs, str):

            addrs = [addrs]

        count = 0

        for addr in addrs:

            code, resp = self.cmd('RCPT TO: <%s>' % addr)

            if code!=250 and code!=251:

                print('%s refused, %s' % (addr, resp))

                count += 1

        assert count!=len(addrs), 'recipient refused, %d, %s' % (code, resp)


        code, resp = self.cmd('DATA')

        assert code==354, 'data refused, %d, %s' % (code, resp)

        return code, resp


    def write(self, content):

        self._sock.write(content)


    def send(self, content=''):

        if content:

            self.write(content)

        self._sock.write('\r\n.\r\n') # the five letter sequence marked for ending

        line = self._sock.readline()

        return (int(line[:3]), line[4:].strip().decode())


    def quit(self):

        self.cmd("QUIT")

        self._sock.close()

 

Terlepas dari IDE yang Anda gunakan, berikut adalah langkah-langkah umum untuk mengunggah pustaka uMail ke board:

1. Pastikan board sudah menggunakan firmware MicroPython. Silakan periksa bagian Prerequisites terlebih dahulu.

2. Buat file baru pada IDE Anda dengan nama `umail.py`, lalu salin kode modul uMail ke dalam file tersebut dan simpan.

3. Hubungkan board dengan komputer dan lakukan komunikasi serial melalui IDE yang digunakan.

4. Unggah file `umail.py` ke board ESP32/ESP8266.

5. Jika proses unggah berhasil, pustaka uMail sudah siap digunakan. Selanjutnya, Anda dapat memanfaatkan fungsi-fungsi yang tersedia dengan mengimpor pustaka tersebut ke dalam kode program menggunakan perintah: 'import umail'

Mengunggah Modul BME280

Untuk membaca data suhu, kelembapan, dan tekanan udara dari sensor BME280, kita akan menggunakan modul berikut. Sebelum diunggah ke board, pastikan file modul tersebut disimpan dengan nama `BME280.py` agar dapat digunakan dengan benar dalam program.

 

from machine import I2C

import time


# BME280 default address.

BME280_I2CADDR = 0x76


# Operating Modes

BME280_OSAMPLE_1 = 1

BME280_OSAMPLE_2 = 2

BME280_OSAMPLE_4 = 3

BME280_OSAMPLE_8 = 4

BME280_OSAMPLE_16 = 5


# BME280 Registers


BME280_REGISTER_DIG_T1 = 0x88  # Trimming parameter registers

BME280_REGISTER_DIG_T2 = 0x8A

BME280_REGISTER_DIG_T3 = 0x8C


BME280_REGISTER_DIG_P1 = 0x8E

BME280_REGISTER_DIG_P2 = 0x90

BME280_REGISTER_DIG_P3 = 0x92

BME280_REGISTER_DIG_P4 = 0x94

BME280_REGISTER_DIG_P5 = 0x96

BME280_REGISTER_DIG_P6 = 0x98

BME280_REGISTER_DIG_P7 = 0x9A

BME280_REGISTER_DIG_P8 = 0x9C

BME280_REGISTER_DIG_P9 = 0x9E


BME280_REGISTER_DIG_H1 = 0xA1

BME280_REGISTER_DIG_H2 = 0xE1

BME280_REGISTER_DIG_H3 = 0xE3

BME280_REGISTER_DIG_H4 = 0xE4

BME280_REGISTER_DIG_H5 = 0xE5

BME280_REGISTER_DIG_H6 = 0xE6

BME280_REGISTER_DIG_H7 = 0xE7


BME280_REGISTER_CHIPID = 0xD0

BME280_REGISTER_VERSION = 0xD1

BME280_REGISTER_SOFTRESET = 0xE0


BME280_REGISTER_CONTROL_HUM = 0xF2

BME280_REGISTER_CONTROL = 0xF4

BME280_REGISTER_CONFIG = 0xF5

BME280_REGISTER_PRESSURE_DATA = 0xF7

BME280_REGISTER_TEMP_DATA = 0xFA

BME280_REGISTER_HUMIDITY_DATA = 0xFD



class Device:

  """Class for communicating with an I2C device.


  Allows reading and writing 8-bit, 16-bit, and byte array values to

  registers on the device."""


  def __init__(self, address, i2c):

    """Create an instance of the I2C device at the specified address using

    the specified I2C interface object."""

    self._address = address

    self._i2c = i2c


  def writeRaw8(self, value):

    """Write an 8-bit value on the bus (without register)."""

    value = value & 0xFF

    self._i2c.writeto(self._address, value)


  def write8(self, register, value):

    """Write an 8-bit value to the specified register."""

    b=bytearray(1)

    b[0]=value & 0xFF

    self._i2c.writeto_mem(self._address, register, b)


  def write16(self, register, value):

    """Write a 16-bit value to the specified register."""

    value = value & 0xFFFF

    b=bytearray(2)

    b[0]= value & 0xFF

    b[1]= (value>>8) & 0xFF

    self.i2c.writeto_mem(self._address, register, value)


  def readRaw8(self):

    """Read an 8-bit value on the bus (without register)."""

    return int.from_bytes(self._i2c.readfrom(self._address, 1),'little') & 0xFF


  def readU8(self, register):

    """Read an unsigned byte from the specified register."""

    return int.from_bytes(

        self._i2c.readfrom_mem(self._address, register, 1),'little') & 0xFF


  def readS8(self, register):

    """Read a signed byte from the specified register."""

    result = self.readU8(register)

    if result > 127:

      result -= 256

    return result


  def readU16(self, register, little_endian=True):

    """Read an unsigned 16-bit value from the specified register, with the

    specified endianness (default little endian, or least significant byte

    first)."""

    result = int.from_bytes(

        self._i2c.readfrom_mem(self._address, register, 2),'little') & 0xFFFF

    if not little_endian:

      result = ((result << 8) & 0xFF00) + (result >> 8)

    return result


  def readS16(self, register, little_endian=True):

    """Read a signed 16-bit value from the specified register, with the

    specified endianness (default little endian, or least significant byte

    first)."""

    result = self.readU16(register, little_endian)

    if result > 32767:

      result -= 65536

    return result


  def readU16LE(self, register):

    """Read an unsigned 16-bit value from the specified register, in little

    endian byte order."""

    return self.readU16(register, little_endian=True)


  def readU16BE(self, register):

    """Read an unsigned 16-bit value from the specified register, in big

    endian byte order."""

    return self.readU16(register, little_endian=False)


  def readS16LE(self, register):

    """Read a signed 16-bit value from the specified register, in little

    endian byte order."""

    return self.readS16(register, little_endian=True)


  def readS16BE(self, register):

    """Read a signed 16-bit value from the specified register, in big

    endian byte order."""

    return self.readS16(register, little_endian=False)



class BME280:

  def __init__(self, mode=BME280_OSAMPLE_1, address=BME280_I2CADDR, i2c=None,

               **kwargs):

    # Check that mode is valid.

    if mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4,

                    BME280_OSAMPLE_8, BME280_OSAMPLE_16]:

        raise ValueError(

            'Unexpected mode value {0}. Set mode to one of '

            'BME280_ULTRALOWPOWER, BME280_STANDARD, BME280_HIGHRES, or '

            'BME280_ULTRAHIGHRES'.format(mode))

    self._mode = mode

    # Create I2C device.

    if i2c is None:

      raise ValueError('An I2C object is required.')

    self._device = Device(address, i2c)

    # Load calibration values.

    self._load_calibration()

    self._device.write8(BME280_REGISTER_CONTROL, 0x3F)

    self.t_fine = 0


  def _load_calibration(self):


    self.dig_T1 = self._device.readU16LE(BME280_REGISTER_DIG_T1)

    self.dig_T2 = self._device.readS16LE(BME280_REGISTER_DIG_T2)

    self.dig_T3 = self._device.readS16LE(BME280_REGISTER_DIG_T3)


    self.dig_P1 = self._device.readU16LE(BME280_REGISTER_DIG_P1)

    self.dig_P2 = self._device.readS16LE(BME280_REGISTER_DIG_P2)

    self.dig_P3 = self._device.readS16LE(BME280_REGISTER_DIG_P3)

    self.dig_P4 = self._device.readS16LE(BME280_REGISTER_DIG_P4)

    self.dig_P5 = self._device.readS16LE(BME280_REGISTER_DIG_P5)

    self.dig_P6 = self._device.readS16LE(BME280_REGISTER_DIG_P6)

    self.dig_P7 = self._device.readS16LE(BME280_REGISTER_DIG_P7)

    self.dig_P8 = self._device.readS16LE(BME280_REGISTER_DIG_P8)

    self.dig_P9 = self._device.readS16LE(BME280_REGISTER_DIG_P9)


    self.dig_H1 = self._device.readU8(BME280_REGISTER_DIG_H1)

    self.dig_H2 = self._device.readS16LE(BME280_REGISTER_DIG_H2)

    self.dig_H3 = self._device.readU8(BME280_REGISTER_DIG_H3)

    self.dig_H6 = self._device.readS8(BME280_REGISTER_DIG_H7)


    h4 = self._device.readS8(BME280_REGISTER_DIG_H4)

    h4 = (h4 << 24) >> 20

    self.dig_H4 = h4 | (self._device.readU8(BME280_REGISTER_DIG_H5) & 0x0F)


    h5 = self._device.readS8(BME280_REGISTER_DIG_H6)

    h5 = (h5 << 24) >> 20

    self.dig_H5 = h5 | (

        self._device.readU8(BME280_REGISTER_DIG_H5) >> 4 & 0x0F)


  def read_raw_temp(self):

    """Reads the raw (uncompensated) temperature from the sensor."""

    meas = self._mode

    self._device.write8(BME280_REGISTER_CONTROL_HUM, meas)

    meas = self._mode << 5 | self._mode << 2 | 1

    self._device.write8(BME280_REGISTER_CONTROL, meas)

    sleep_time = 1250 + 2300 * (1 << self._mode)


    sleep_time = sleep_time + 2300 * (1 << self._mode) + 575

    sleep_time = sleep_time + 2300 * (1 << self._mode) + 575

    time.sleep_us(sleep_time)  # Wait the required time

    msb = self._device.readU8(BME280_REGISTER_TEMP_DATA)

    lsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 1)

    xlsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 2)

    raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4

    return raw


  def read_raw_pressure(self):

    """Reads the raw (uncompensated) pressure level from the sensor."""

    """Assumes that the temperature has already been read """

    """i.e. that enough delay has been provided"""

    msb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA)

    lsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 1)

    xlsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 2)

    raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4

    return raw


  def read_raw_humidity(self):

    """Assumes that the temperature has already been read """

    """i.e. that enough delay has been provided"""

    msb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA)

    lsb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA + 1)

    raw = (msb << 8) | lsb

    return raw


  def read_temperature(self):

    """Get the compensated temperature in 0.01 of a degree celsius."""

    adc = self.read_raw_temp()

    var1 = ((adc >> 3) - (self.dig_T1 << 1)) * (self.dig_T2 >> 11)

    var2 = ((

        (((adc >> 4) - self.dig_T1) * ((adc >> 4) - self.dig_T1)) >> 12) *

        self.dig_T3) >> 14

    self.t_fine = var1 + var2

    return (self.t_fine * 5 + 128) >> 8


  def read_pressure(self):

    """Gets the compensated pressure in Pascals."""

    adc = self.read_raw_pressure()

    var1 = self.t_fine - 128000

    var2 = var1 * var1 * self.dig_P6

    var2 = var2 + ((var1 * self.dig_P5) << 17)

    var2 = var2 + (self.dig_P4 << 35)

    var1 = (((var1 * var1 * self.dig_P3) >> 8) +

            ((var1 * self.dig_P2) >> 12))

    var1 = (((1 << 47) + var1) * self.dig_P1) >> 33

    if var1 == 0:

      return 0

    p = 1048576 - adc

    p = (((p << 31) - var2) * 3125) // var1

    var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25

    var2 = (self.dig_P8 * p) >> 19

    return ((p + var1 + var2) >> 8) + (self.dig_P7 << 4)


  def read_humidity(self):

    adc = self.read_raw_humidity()

    # print 'Raw humidity = {0:d}'.format (adc)

    h = self.t_fine - 76800

    h = (((((adc << 14) - (self.dig_H4 << 20) - (self.dig_H5 * h)) +

         16384) >> 15) * (((((((h * self.dig_H6) >> 10) * (((h *

                          self.dig_H3) >> 11) + 32768)) >> 10) + 2097152) *

                          self.dig_H2 + 8192) >> 14))

    h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4)

    h = 0 if h < 0 else h

    h = 419430400 if h > 419430400 else h

    return h >> 12


  @property

  def temperature(self):

    "Return the temperature in degrees."

    t = self.read_temperature()

    ti = t // 100

    td = t - ti * 100

    return "{}.{:02d}C".format(ti, td)


  @property

  def pressure(self):

    "Return the temperature in hPa."

    p = self.read_pressure() // 256

    pi = p // 100

    pd = p - pi * 100

    return "{}.{:02d}hPa".format(pi, pd)


  @property

  def humidity(self):

    "Return the humidity in percent."

    h = self.read_humidity()

    hi = h // 1024

    hd = h * 100 // 1024 - hi * 100

    return "{}.{:02d}%".format(hi, hd)

 

Terlepas dari IDE yang Anda gunakan, berikut adalah langkah-langkah umum untuk mengunggah pustaka BME280 ke board:

1. Pastikan board telah menggunakan firmware MicroPython. Silakan periksa bagian Prerequisites untuk memastikan hal tersebut.

2. Buat file baru pada IDE dengan nama `BME280.py`, lalu salin kode modul BME280 ke dalam file tersebut dan simpan.

3. Hubungkan board ke komputer dan lakukan komunikasi serial melalui IDE yang digunakan.

4. Unggah file `BME280.py` ke board ESP32/ESP8266.

Setelah proses unggah selesai, pustaka BME280 sudah siap digunakan. Selanjutnya, Anda dapat memanggil fungsi-fungsi yang tersedia dengan mengimpor pustaka tersebut ke dalam kode program menggunakan perintah: 'import BME280'

Mengirim Data Sensor melalui Email – MicroPython (Kode Program)

Pada tahap ini, Anda seharusnya sudah berhasil mengunggah file `umail.py` dan `BME280.py` ke board. Kedua pustaka tersebut diperlukan agar ESP32/ESP8266 dapat membaca data dari sensor BME280 sekaligus mengirimkannya melalui email.

 

Script berikut akan mengirimkan sebuah email berisi data pembacaan sensor terkini setiap kali board ESP32/ESP8266 dinyalakan atau dilakukan proses reset.

 

import umail 

import network

import BME280

from machine import Pin, SoftI2C


# Your network credentials

ssid = 'REPLACE_WITH_YOUR_SSID'

password = 'REPLACE_WITH_YOUR_PASSWORD'


# Email details

sender_email = 'REPLACE_WITH_THE_SENDER_EMAIL'

sender_name = 'ESP32' #sender name

sender_app_password = 'REPLACE_WITH_THE_SENDER_EMAIL_APP_PASSWORD'

recipient_email ='REPLACE_WITH_THE_RECIPIENT_EMAIL'

email_subject ='BME280 Sensor Readings'


# BME280 pin assignment - ESP32

i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=10000)

# BME280 pin assignment - ESP8266

#i2c = I2C(scl=Pin(5), sda=Pin(4), freq=10000)

bme = BME280.BME280(i2c=i2c)


def read_bme_sensor():

  try:

    temp = str(bme.temperature[:-1]) + " ºC"

    #uncomment for temperature in Fahrenheit

    #temp = str((bme.read_temperature()/100) * (9/5) + 32) + " 潞F"

    hum = str(bme.humidity[:-1]) + " %"

    pres = str(bme.pressure[:-3]) + " hPa"


    return temp, hum, pres

    #else:

    #  return('Invalid sensor readings.')

  except OSError as e:

    return('Failed to read sensor.')

  

def connect_wifi(ssid, password):

  #Connect to your network

  station = network.WLAN(network.STA_IF)

  station.active(True)

  station.connect(ssid, password)

  while station.isconnected() == False:

    pass

  print('Connection successful')

  print(station.ifconfig())

    

# Connect to your network

connect_wifi(ssid, password)


# Get sensor readings

temp, hum, pres = read_bme_sensor()

print(temp)

print(hum)

print(pres)


# Send the email

smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True) # Gmail's SSL port

smtp.login(sender_email, sender_app_password)

smtp.to(recipient_email)

smtp.write("From:" + sender_name + "<"+ sender_email+">\n")

smtp.write("Subject:" + email_subject + "\n")

smtp.write("Temperature " + temp + "\n")

smtp.write("Humidity " + hum + "\n")

smtp.write("Pressure " + pres + "\n")

smtp.send()

smtp.quit()

 

Sebelum mengunggah kode ke board, Anda perlu menyesuaikan beberapa parameter sesuai dengan konfigurasi Anda, yaitu SSID dan password Wi-Fi, alamat email pengirim, nama pengirim, App Password yang sesuai, alamat email penerima, serta subjek email.

 

Setelah seluruh parameter diisi dengan benar, kode dapat diunggah ke board. Pastikan file program disimpan dengan nama `main.py`, karena file dengan nama inilah yang akan dieksekusi secara otomatis saat ESP32/ESP8266 dinyalakan. Jika menggunakan nama file lain, program tidak akan berjalan.

Cara Kerja Program

Silakan lanjutkan membaca untuk memahami penjelasan alur kerja kode, atau langsung menuju bagian Demonstrasi jika ingin melihat hasil akhirnya.

Menyertakan Library

Langkah pertama adalah menyertakan pustaka-pustaka yang diperlukan. Library uMail digunakan untuk mengirim email dan telah diunggah sebelumnya ke board. Library network digunakan untuk mengatur ESP32/ESP8266 sebagai Wi-Fi station agar dapat terhubung ke jaringan internet (jaringan lokal).

 

Selain itu, modul BME280 diimpor untuk membaca data dari sensor BME280, serta kelas pin dan I2C dari modul machine digunakan untuk membangun komunikasi I2C antara board dan sensor.

 

import umail # Micropython lib to send emails: https://github.com/shawwwn/uMail

import network

import BME280

from machine import Pin, SoftI2C

 

Kredensial Jaringan

Masukkan kredensial jaringan Anda, yaitu SSID dan password Wi-Fi, ke dalam variabel berikut agar board dapat terhubung ke jaringan internet.

 

ssid = 'REPLACE_WITH_YOUR_SSID'

password = 'REPLACE_WITH_YOUR_PASSWORD'

 

Detail Email

Masukkan informasi email yang diperlukan, yaitu alamat email pengirim, nama pengirim, serta App Password yang sesuai. Pastikan Anda telah membuat App Password, karena penggunaan password email biasa tidak akan berfungsi. Silakan merujuk ke panduan pembuatan App Password yang telah dijelaskan sebelumnya.

 

# Email details

sender_email = 'REPLACE_WITH_THE_SENDER_EMAIL'

sender_name = 'ESP32' #sender name

sender_app_password = 'REPLACE_WITH_THE_SENDER_EMAIL_APP_PASSWORD'

 

Masukkan alamat email penerima ke dalam variabel `recipient_email` berikut.

 

recipient_email ='REPLACE_WITH_THE_RECIPIENT_EMAIL'

 

BME280

Subjek email secara default diatur sebagai “BME280 Sensor Readings”, namun Anda dapat mengubahnya sesuai kebutuhan dengan menyesuaikan nilai pada variabel `email_subject`.

 

email_subject ='BME280 Sensor Readings'

 

Buat objek I2C menggunakan pin I2C pada board. Pada ESP32, komunikasi I2C menggunakan GPIO 22 sebagai SCL dan GPIO 21 sebagai SDA.

 

i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=10000)

 

Jika Anda menggunakan board ESP8266, gunakan GPIO 4 sebagai SDA dan GPIO 5 sebagai **SCL** sebagai pengganti.

 

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=10000)

 

Jika Anda menggunakan board dengan konfigurasi pin I2C yang berbeda, pastikan untuk menyesuaikan baris kode tersebut sesuai dengan pin yang digunakan.

 

Setelah objek I2C berhasil dibuat, selanjutnya kita dapat membuat objek BME280 (pada contoh ini diberi nama `bme`) yang akan berkomunikasi melalui pin-pin I2C tersebut.

 

bme = BME280.BME280(i2c=i2c)

 

Membaca BME280: Suhu, Kelembaban, dan Tekanan

Untuk membaca data dari sensor BME280, kita membuat sebuah fungsi bernama `read_bme_sensor()` yang mengembalikan nilai suhu, kelembapan, dan tekanan dalam bentuk string beserta satuan masing-masing. Format ini sangat ideal untuk langsung digunakan dalam isi email.

 

def read_bme_sensor():

  try:

    temp = str(bme.temperature[:-1]) + " ºC"

    #uncomment for temperature in Fahrenheit

    #temp = str((bme.read_temperature()/100) * (9/5) + 32) + " ºF"

    hum = str(bme.humidity[:-1]) + " %"

    pres = str(bme.pressure[:-3]) + " hPa"


    return temp, hum, pres

    #else:

    #  return('Invalid sensor readings.')

  except OSError as e:

    return('Failed to read sensor.')

 

Secara default, fungsi ini mengembalikan nilai suhu dalam satuan derajat Celcius. Jika Anda ingin mendapatkan suhu dalam satuan Fahrenheit, cukup hapus komentar pada baris kode berikut:

 

#temp = str((bme.read_temperature()/100) * (9/5) + 32) + " ºF"

 

Menghubungkan ke Wi-Fi

Untuk menghubungkan board ke jaringan Wi-Fi, kita membuat sebuah fungsi bernama `connect_wifi()` yang menerima SSID dan password dari jaringan yang ingin digunakan sebagai argumen. Fungsi ini harus dipanggil nantinya agar board ESP dapat benar-benar terhubung ke internet.

 

def connect_wifi(ssid, password):

  #Connect to your network

  station = network.WLAN(network.STA_IF)

  station.active(True)

  station.connect(ssid, password)

  while station.isconnected() == False:

    pass

  print('Connection successful')

  print(station.ifconfig())

 

Sebelum mengirim email, kita perlu menghubungkan ESP32/ESP8266 ke internet. Panggil fungsi `connect_wifi()` dan berikan SSID serta password sebagai argumennya.

 

# Connect to your network

connect_wifi(ssid, password)

 

Mendapatkan Data Terbaru

Untuk memperoleh data dari sensor dalam format yang diinginkan, cukup panggil fungsi `read_bme_sensor()` yang telah dibuat sebelumnya. Nilai suhu, kelembapan, dan tekanan disimpan pada variabel `temp`, `hum`, dan `pres`. Ketiga variabel ini berupa string yang sudah menyertakan satuan masing-masing (ºC, %, dan hPa). Baris-baris kode berikut akan mengambil pembacaan terbaru dan menampilkannya di shell.

 

# Get sensor readings

temp, hum, pres = read_bme_sensor()

print(temp)

print(hum)

print(pres)

 

Mengirim Email

Sekarang, kita dapat mulai menyiapkan dan mengirim email.

Mulailah dengan membuat SMTP client menggunakan pengaturan SMTP dari penyedia email Anda, dan simpan dengan nama `smtp`. Pada contoh ini, digunakan akun Gmail. Jika Anda menggunakan penyedia email lain, ubah pengaturan server, port, serta tentukan apakah SSL diperlukan atau tidak sesuai kebutuhan.

 

smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True) # Gmail's SSL port

 

Selanjutnya, login ke akun email Anda menggunakan metode `login()` pada objek `smtp`, dengan memasukkan alamat email dan App Password yang sesuai sebagai argumen.

 

smtp.login(sender_email, sender_app_password)

 

Tentukan penerima email menggunakan metode `to()` dan berikan alamat email penerima sebagai argumennya:

 

smtp.to(recipient_email)

 

Selanjutnya, gunakan metode `write()` untuk menulis isi email. Metode ini juga dapat digunakan untuk menetapkan nama pengirim seperti contoh berikut.

 

smtp.write("From:" + sender_name + "<"+ sender_email+">\n")

 

Dan Anda dapat menggunakan baris kode berikut untuk menetapkan subjek email.

 

smtp.write("Subject:" + email_subject + "\n")

 

Terakhir, Anda dapat menulis isi email. Pada contoh ini, yang dikirim adalah nilai suhu, kelembaban, dan tekanan dalam badan email, namun Anda juga bisa menambahkan teks tambahan atau menggunakan HTML untuk memformat isi email. Metode `write()` akan mengirim email tersebut ke server SMTP.

 

smtp.write("Temperature " + temp + "\n")

smtp.write("Humidity " + hum + "\n")

smtp.write("Pressure " + pres + "\n")

 

Jika Anda perlu mengirim pesan email yang panjang, bagi isi email menjadi beberapa bagian kecil dan kirim setiap bagian menggunakan metode `write()`, lihat dokumentasi library uMail untuk referensi lebih lengkap.

 

Terakhir, gunakan metode `send()` agar server SMTP mengirimkan email tersebut ke penerima.

 

smtp.send()

 

Terakhir, tutup koneksi dengan server menggunakan metode `quit()`.

 

smtp.quit()

 

Demonstrasi

Setelah mengunggah modul uMail, BME280, dan skrip `main.py` ke board, jalankan kode atau lakukan reset/restart pada board. Anda seharusnya melihat pesan serupa di shell yang menandakan bahwa board berhasil terhubung ke internet dan menampilkan pembacaan sensor terkini.



Setelah beberapa saat, Anda akan menerima email baru di akun email penerima.



Buka email tersebut untuk memeriksa data pembacaan sensor terkini.



 

 

 

 

 

 

 

 

Siap Untuk Membuat Proyek Impianmu Menjadi Kenyataan?

Klik di sini untuk chat langsung via WhatsApp dan dapatkan dukungan langsung dari tim ahli kami! 

 

0 on: "MicroPython - Mengirim Data Sensor melalui Email menggunakan ESP32/ESP8266 (BME280)"