STACK & PLAY
Standard 5×5cm functionally stacking modularized components hardware system.
ESP32 microcontroller、 microSD card slot、USB-C、extension connectors.
The Stacking Functional MODULES Built for Customized Assembly.
Easy Deployment with multifunctional BASE.
STACK SERIES
5×5CM MODULAR STACKABLE
Standard Size
Better Display
User Friendly
For comprehensive application
STICK SERIES
COMPACT IoT SOLUTION
All-in-one
Best in Price
Low power consumption
For IoT edge application
ATOM SERIES
SMALL SIZE, BIG USE!
Smallest ESP32 devkit
IoT edge nodes
Miniature embedded device
For smart home and industry control application
FROM PROTOTYPING TO COMMERCIAL LEVEL
END TO END IoT EDGE SOLUTIONS
SMART FACTORY
Improving efficiency, preventing risks and delivering results with connected IoT devices.
SMART AGRICULTURE
Using sensors to collect data and using edge computing devices to analyze data, helps automate farming and breeding sectors.
SMART RETAIL
Obtain and analyze data about customer behavior; Automate shopping process and optimize shopping experience.
WEATHER STATION
Field ready data-collection solutions for environmental and meteorological monitoring.
WHY CHOOSE US?
FULL RANGE IoT MODULES
From the esp32-s3 controllers, arduino esp32, esp32 kits, esp32 camera, communication modules to the sensors including sensors like tof sensor and otherand actuators; high performance, high reliability, high scalability, and quick access to cloud platforms like Azure, AWS.
QUICK DEVELOPMENT AND VERIFICATION
Stackable standardization system to facilitate rapid concept proofing, rapid verification, and rapid shipment; ISO9001 international quality system certification, FCC, CE, TELEC product certifications to ensure timeline and quality.
TECHNICAL SERVICE
DOCS database, forums and etc provide technical services, UIFlow visual rapid development tools, complete API interfaces, greatly shorten the integration time, and help product mass production.
OPEN PLATFORM
Open-source hardware, open API interface, diverse cooperation forms, more cost-effective.
88
COUNTRIES
52668
GLOBAL DEVELOPERS
280
PRODUCTS
THE LATEST FROM M5STACK

Source: AguacaTEC
Author: TitoTB

In this article, we will integrate the M5Stack Air Quality Kit with Home Assistant to monitor air quality.

Index

  • Air Quality Sensor
  • M5Stack Air Quality Kit
  • Prerequisites
  • Configuration in ESPHome
  • Device Information

Air Quality Sensor

While air quality may not be a concern for everyone, those of us living in large cities or near industrial areas are increasingly worried about the air we breathe at home. This concern is not unfounded—numerous studies have shown that long-term exposure to pollutants can lead to respiratory diseases such as asthma and bronchitis. Over time, it can also shorten lifespan and increase the risk of chronic illnesses like lung cancer.

From this perspective, home automation can help mitigate these effects by monitoring air quality, sending alerts when pollution levels rise, or even activating ventilation or air purification systems. If you're concerned about overall environmental pollution, you can refer to indexes like the World Air Quality Index.

However, whether you distrust external data (for instance, if monitoring stations are conveniently placed in green zones) or simply want to measure the specific data in your own home, an air quality sensor is essential. When it comes to finding a sensor that is comprehensive, integrable, and reasonably priced, debates always arise.

M5Stack Air Quality Kit

M5Stack is a well-known brand that offers devices like the M5Stack CoreS3SE and the historically significant Atom Echo. In this case, we’ll integrate the M5Stack Air Quality Kit with Home Assistant. This device is based on the ESP32S3FN8 chip and can measure CO2, VOCs, PM1.0, PM2.5, PM4, and PM10 particles, along with temperature and humidity (though some reviews suggest the accuracy of the latter two may be questionable). It also features an e-ink display and a built-in battery.

 

By the way, while this article focuses on integrating the M5Stack  Air Quality Kit with Home Assistant, you can also use it directly with your mobile device to monitor its readings. The video below explains the setup process.

Prerequisites

To integrate the M5Stack Air Quality Kit into Home Assistant, you will need:

  • M5Stack Air Quality Kit 
  • ESPHome installed in Home Assistant.
  • A USB-C cable to power the DATA board (a charging-only cable will not allow software installation).

🥑 If you’re new to ESPHome, I recommend checking out the Academy workshop to get the most of it!

Configuration in ESPHome

Follow these steps to integrate the M5Stack Air Quality Kit into Home Assistant:

1. In Home Assistant, go to your ESPHome plugin, click “New Device,” and then click “Continue.”

2. Name your device (e.g., “ Air Quality Kit”) and click “Next.”

3. Select “ESP32-S3” as the device type. You'll notice that a new block has been created for your device in the background.

4. Click “Skip” and click “Edit” on the device block above. Copy the code that appears and save it, as you will need some parts of it later.

5. Copy the following code (which I found on reddit and edited slightly) and replace the above code in ESPHome.

substitutions:
  devicename: lounge-airq
  friendlyname: Lounge AirQ
  location: Lounge
  sensor_interval: 10s

esphome:
  name: ${devicename}
  friendly_name: ${friendlyname}
  area: ${location}
  platformio_options:
    board_build.mcu: esp32s3
    board_build.name: "M5Stack StampS3"
    board_build.upload.flash_size: 8MB
    board_build.upload.maximum_size: 8388608
    board_build.vendor: M5Stack
  on_boot:
  - priority: 800
    then:
      - output.turn_on: enable
  - priority: 800
    then:
      - pcf8563.read_time

esp32:
  board: esp32-s3-devkitc-1 #m5stack-stamps3
  variant: esp32s3
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: REDACTED

ota:
  - platform: esphome
    password: REDACTED

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Lounge-Airq Fallback Hotspot"
    password: REDACTED

captive_portal:

output:
  - platform: gpio
    pin: GPIO10
    id: enable

web_server:
   port: 80
   include_internal: true

i2c:
  sda: GPIO11
  scl: GPIO12
  scan: true
  frequency: 100kHz
  id: bus_a

spi:
  clk_pin: GPIO05
  mosi_pin: GPIO06

time:
  - platform: pcf8563
    address: 0x51
    update_interval: 10min
  - platform: homeassistant
    id: esptime

light:
  - platform: esp32_rmt_led_strip
    rgb_order: GRB
    pin: GPIO21
    num_leds: 1
    rmt_channel: 0
    chipset: SK6812
    name: "LED"
    restore_mode: ALWAYS_OFF
    id: id_led

text_sensor:
  - platform: wifi_info
    ip_address:
      name: IP
    ssid:
      name: SSID
    bssid:
      name: BSSID
    mac_address:
      name: MAC
    dns_address:
      name: DNS

  - platform: template
    name: "VOC IAQ Classification"
    id: iaq_voc
    icon: "mdi:checkbox-marked-circle-outline"
    lambda: |-
      if (int(id(voc).state) < 100.0) {
        return {"Great"};
      }
      else if (int(id(voc).state) <= 200.0) {
        return {"Good"};
      }
      else if (int(id(voc).state) <= 300.0) {
        return {"Light"};
      }
      else if (int(id(voc).state) <= 400.0) {
        return {"Moderate"};
      }
      else if (int(id(voc).state) <= 500.0) {
        return {"Heavy"};
      }
      else {
        return {"unknown"};
      }

  - platform: template
    name: "NOX IAQ Classification"
    id: iaq_nox
    icon: "mdi:checkbox-marked-circle-outline"
    lambda: |-
      if (int(id(nox).state) < 100.0) {
        return {"Great"};
      }
      else if (int(id(nox).state) <= 200.0) {
        return {"Good"};
      }
      else if (int(id(nox).state) <= 300.0) {
        return {"Light"};
      }
      else if (int(id(nox).state) <= 400.0) {
        return {"Moderate"};
      }
      else if (int(id(nox).state) <= 500.0) {
        return {"Heavy"};
      }
      else {
        return {"unknown"};
      }

sensor:
  - platform: scd4x
    co2:
      name: CO2
      id: CO2
      filters:
        - lambda: |-
            float MIN_VALUE = 300.0;
            float MAX_VALUE = 2500.0;
            if (MIN_VALUE <= x && x <= MAX_VALUE) return x;
            else return {};         
    temperature:
      name: CO2 Temperature
      id: CO2_temperature
      filters:
        - lambda: |-
            float MIN_VALUE = -40.0;
            float MAX_VALUE = 100.0;
            if (MIN_VALUE <= x && x <= MAX_VALUE) return x;
            else return {};      
    humidity:
      name: CO2 Humidity
      id: CO2_humidity
      filters:
        - lambda: |-
            float MIN_VALUE = 0.0;
            float MAX_VALUE = 100.0;
            if (MIN_VALUE <= x && x <= MAX_VALUE) return x;
            else return {};      
    altitude_compensation: 0m
    address: 0x62
    update_interval: $sensor_interval

  - platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
    name: "Wifi Signal dB"
    id: wifi_signal_db
    update_interval: 60s
    entity_category: "diagnostic"

  - platform: sen5x
    id: sen55
    pm_1_0:
      name: "PM 1"
      id: PM1_0
      accuracy_decimals: 2
    pm_2_5:
      name: "PM 2.5"
      id: PM2_5
      accuracy_decimals: 2
    pm_4_0:
      name: "PM 4"
      id: PM4_0
      accuracy_decimals: 2
    pm_10_0:
      name: "PM 10"
      id: PM10_0
      accuracy_decimals: 2
    temperature:
      name: "SEN55 Temperature"
      id: sen55_temperature
      accuracy_decimals: 2
    humidity:
      name: "SEN55 Humidity"
      id: sen55_humidity
      accuracy_decimals: 2
    voc:
      name: VOC
      id: voc
      accuracy_decimals: 2
      algorithm_tuning:
        index_offset: 100
        learning_time_offset_hours: 12
        learning_time_gain_hours: 12
        gating_max_duration_minutes: 180
        std_initial: 50
        gain_factor: 230
    nox:
      name: NOX
      id: nox
      accuracy_decimals: 2      
      algorithm_tuning:
        index_offset: 100
        learning_time_offset_hours: 12
        learning_time_gain_hours: 12
        gating_max_duration_minutes: 180
        std_initial: 50
        gain_factor: 230
    temperature_compensation:
      offset: 0
      normalized_offset_slope: 0
      time_constant: 0
    acceleration_mode: low
    store_baseline: true
    address: 0x69
    update_interval: $sensor_interval

  - platform: template
    name: Temperature
    id: temperature
    lambda: |-
      return (( id(sen55_temperature).state + id(CO2_temperature).state ) / 2 ) - id(temperature_offset).state;
    unit_of_measurement: "°C"
    icon: "mdi:thermometer"
    device_class: "temperature"
    state_class: "measurement"
    update_interval: $sensor_interval
    accuracy_decimals: 2

  - platform: template
    name: Humidity
    id: humidity
    lambda: |-
      return (( id(sen55_humidity).state + id(CO2_humidity).state ) / 2) - id(humidity_offset).state;
    unit_of_measurement: "%"
    icon: "mdi:water-percent"
    device_class: "humidity"
    state_class: "measurement"    
    update_interval: $sensor_interval
    accuracy_decimals: 2

binary_sensor:
  - platform: gpio
    name: Button A
    pin:
      number: GPIO0
      ignore_strapping_warning: true
      mode:
        input: true
      inverted: true
    on_press:
      then:
        - component.update: disp
      
  - platform: gpio
    pin:
      number: GPIO08
      mode:
        input: true
        pullup: true
      inverted: true
    name: Button B
    
  - platform: gpio
    pin:
      number: GPIO46
      ignore_strapping_warning: true
    name: Button Hold

  - platform: gpio
    pin: 
      number: GPIO42
    name: Button Power

button:
  - platform: restart
    name: Restart
    
  - platform: template
    name: "CO2 Force Manual Calibration"
    entity_category: "config"
    on_press:
      then:
        - scd4x.perform_forced_calibration:
            value: !lambda 'return id(co2_cal).state;'

  - platform: template
    name: "SEN55 Force Manual Clean"
    entity_category: "config"
    on_press:
      then:
        - sen5x.start_fan_autoclean: sen55

number:
  - platform: template
    name: "CO2 Calibration Value"
    optimistic: true
    min_value: 400
    max_value: 1000
    step: 5
    id: co2_cal
    icon: "mdi:molecule-co2"
    entity_category: "config"

  - platform: template
    name: Humidity Offset
    id: humidity_offset
    restore_value: true
    initial_value: 0.0
    min_value: -70.0
    max_value: 70.0
    entity_category: "CONFIG"
    unit_of_measurement: "%"
    optimistic: true
    update_interval: never
    step: 0.1
    mode: box

  - platform: template
    name: Temperature Offset
    id: temperature_offset
    restore_value: true
    initial_value: 0.0
    min_value: -70.0
    max_value: 70.0
    entity_category: "CONFIG"
    unit_of_measurement: "°C"
    optimistic: true
    update_interval: never
    step: 0.1
    mode: box

display:
  - platform: waveshare_epaper
    model: 1.54inv2
    id: disp
    cs_pin: GPIO04
    dc_pin: GPIO03
    reset_pin: GPIO02
    busy_pin:
      number: GPIO01
      inverted: false
    full_update_every: 6
    reset_duration: 2ms
    update_interval: 10s
    lambda: |-
      auto now = id(esptime).now().strftime("%H:%M %d/%m/%y").c_str();
      it.printf(it.get_width()/2, 0, id(f12), TextAlign::TOP_CENTER, "${location} @ %s", now);

      it.print(0, 23, id(f24), TextAlign::TOP_LEFT, "PM 1: "); 
      it.print(0, 48, id(f24), TextAlign::TOP_LEFT, "PM 2.5: "); 
      it.print(0, 73, id(f24), TextAlign::TOP_LEFT, "PM 4: "); 
      it.print(0, 98, id(f24), TextAlign::TOP_LEFT, "PM 10: "); 
      it.print(0, 123, id(f24), TextAlign::TOP_LEFT, "CO2: "); 
      it.print(0, 148, id(f24), TextAlign::TOP_LEFT, "VOC: ");
      it.print(0, 173, id(f24), TextAlign::TOP_LEFT, "NOX: ");

      it.printf(it.get_width(), 23, id(f24), TextAlign::TOP_RIGHT, "%.0f", id(PM1_0).state);
      it.printf(it.get_width(), 48, id(f24), TextAlign::TOP_RIGHT, "%.0f", id(PM2_5).state);
      it.printf(it.get_width(), 73, id(f24), TextAlign::TOP_RIGHT, "%.0f", id(PM4_0).state); 
      it.printf(it.get_width(), 98, id(f24), TextAlign::TOP_RIGHT, "%.0f", id(PM10_0).state);
      it.printf(it.get_width(), 123, id(f24), TextAlign::TOP_RIGHT, "%.0fppm", id(CO2).state);
      it.printf(it.get_width(), 148, id(f24), TextAlign::TOP_RIGHT, "%.0f", id(voc).state);
      it.printf(it.get_width(), 173, id(f24), TextAlign::TOP_RIGHT, "%.0f", id(nox).state);

font:
  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 500
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']
    id: f16
    size: 16
  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 500
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']
    id: f18
    size: 18
  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 500
    id: f12
    size: 12
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']
  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 500
    id: f24
    size: 24
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']
  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 500
    id: f36
    size: 36
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']
  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 500
    id: f48
    size: 48
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']
  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 500
    id: f32
    size: 32
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']

  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 500
    id: f64
    size: 64
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']

  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 800
    id: f64b
    size: 64
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']

  - file:
      type: gfonts
      family: Noto Sans Display
      weight: 800
    id: f55b
    size: 55
    glyphs: ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/', 'µ', '³', '’']

  - file: 
      type: gfonts
      family: Material Symbols Sharp
      weight: 400
    id: font_weather_icons_xsmall
    size: 20
    glyphs:
      - "\U0000F159" # clear-night
      - "\U0000F15B" # cloudy
      - "\U0000F172" # partlycloudy
      - "\U0000E818" # fog      
      - "\U0000F67F" # hail
      - "\U0000EBDB" # lightning, lightning-rainy
      - "\U0000F61F" # pouring
      - "\U0000F61E" # rainy
      - "\U0000F61C" # snowy
      - "\U0000F61D" # snowy-rainy
      - "\U0000E81A" # sunny
      - "\U0000EFD8" # windy, windy-variant
      - "\U0000F7F3" # exceptional
  - file: 
      type: gfonts
      family: Material Symbols Sharp
      weight: 400
    id: font_weather_icons_small
    size: 32
    glyphs:
      - "\U0000F159" # clear-night
      - "\U0000F15B" # cloudy
      - "\U0000F172" # partlycloudy
      - "\U0000E818" # fog      
      - "\U0000F67F" # hail
      - "\U0000EBDB" # lightning, lightning-rainy
      - "\U0000F61F" # pouring
      - "\U0000F61E" # rainy
      - "\U0000F61C" # snowy
      - "\U0000F61D" # snowy-rainy
      - "\U0000E81A" # sunny
      - "\U0000EFD8" # windy, windy-variant
      - "\U0000F7F3" # exceptional

  - file:
      type: gfonts
      family: Open Sans
      weight: 700    
    id: font_clock
    glyphs: "0123456789:"
    size: 70
  - file:
      type: gfonts
      family: Open Sans
      weight: 700    
    id: font_clock_big
    glyphs: "0123456789:"
    size: 100
  - file: "gfonts://Roboto"
    id: font_temp
    size: 28
  - file:
      type: gfonts
      family: Open Sans
      weight: 500    
    id: font_small
    size: 30
    glyphs: "!\"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz→»"
  - file:
      type: gfonts
      family: Open Sans
      weight: 500    
    id: font_medium
    size: 45
    glyphs: "!\"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz→»"
  - file:
      type: gfonts
      family: Open Sans
      weight: 300    
    id: font_xsmall
    size: 16  
    glyphs: "!\"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz→»"



    

 

6. Important: This code does not include the credentials for connecting the device to your Wi-Fi and Home Assistant instance, so you will need to enter them manually. Specifically, I am referring to the following lines of code that you copied in step 4.

# Enable Home Assistant API
api:
  encryption:
    key: "bg6hash6sjdjsdjk02hh0qnQeYVwm123vdfKE8BP5"

ota:
  - platform: esphome
    password: "asddasda27aab65a48484502b332f"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Assist Fallback Hotspot"
    password: "ZsasdasdHGP2234"



    

 

7. What you need to do is find the corresponding lines in the code (at the beginning) and add the necessary information.

8. Now, click “Save” and “Install.” Select “Manual download” and wait for the code to compile.

9. When finished, select the “Modern format” option to download the corresponding .bin” file.

10. Connect the M5Stack Air Quality Kit to your computer using the USB-C data cable via the port on the bottom.

11. Now go to the ESPHome page   and click "Connect." In the pop-up window, select your board and click "Connect."

12. Now click on “Install” and select the '.bin' file obtained in step 9. Again, click on “Install”.

13. Go back to Home Assistant and navigate to Settings > Devices & Services. Your device should be discovered and appear at the top, ready for you to click the “Configure” button. If not, click the “Add Integration” button, search for "ESPHome," and enter your board’s IP address in the "Host" field.

Device information

If you navigate to Settings > Devices & Services > ESPHome and select the M5Stack Air Quality Kit, you'll find several entities providing information about air quality.

Additionally, the buttons on the device's top-left corner have also been exposed as entities. This means you can create an automation to trigger an action when you press them, such as activating your ventilation system.

To set this up, go to Settings > Automations and Scenes > Create Automation. In the "When" section, add a "State" trigger. In the entity field, select the one corresponding to your device (e.g., 'binary_sensor.airq_button_a'), and in the "To" field, choose "On." Then, simply add the desired actions.

On November 18, 2024, M5Stack opened its doors to individual visitors for the first time. More than 70 visitors from all around the world attended the event, with some showcasing their projects built with M5 products or sharing their stories with M5Stack.

M5Stack Open Day 2024

The event began at 3:00 PM, with many visitors checking in and receiving their gifts—custom T-shirts featuring the M5Stack logo. After a group photo, the first agenda kicked off: The Factory and Office Tour.

M5Stack Factory and Office Tour

The visitors were divided into three groups, with introductions provided in Chinese, English, and Japanese. M5Stack operates an all-in-one facility where product design, production, packaging, quality control, marketing, and shipping are seamlessly managed under one place. Visitors could take a close look at the whole flow.

Factory of M5Stack

In the show board area, we display all the products we've created so far, including the classic 5x5 stack series—such as M5Basic Core, M5Core2, M5Core3, and Stick series—like the M5StickC, along with the Stamp Series (M5Cardputer, M5StampFly), and the Atom series (M5Atom Echo), among others. M5Stack’s CEO, Jimmy Lai, also explains "What is M5Stack?"

M5Stack product show board

M5Stack is an open-source hardware IoT solution provider, primarily focused on products built around the ESP32. We also offer a range of accessories and our own visual programming platform, UIFlow. The "M" in M5Stack stands for Module, "5" represents the 5x5 cm size, and "Stack" refers to their stackable design. 

M5Stack is committed to delivering convenient, stackable and easy-to-use development components and tools, with at least one new product every Friday, we launch over 50 new products every year. We provide not only standard products, also customized products. Our partner includes Amazon, Microsoft, Arduino, SONY, etc.

Projects or Stories with M5Stack

After the tour, it’s time for the Meetup. This year, we have 9 speakers. Jimmy began by sharing the company’s history, followed by presentations from the speakers. TAKASU Masakazu shared the success stories of M5Stack in Japan, where the Japanese market accounts for 35% of M5Stack’s global sales. Many companies and schools in Japan use M5Stack products, and you can even find books on how to use M5Stack products on Amazon. 

TAKASU Masakazu share the M5Stack's successful story in Japan

Other speakers introduced their innovative projects, including the Creative Dot Matrix Clock, the M5Unified Library, M5Cuffbox, and the Blue Tears Incubator, how to make stack-chan bigger, etc.

speaker shows his 3 projects using M5stack's product

It was a truly enjoyable experience to come together with M5Stack fans from all over. We appreciate everyone’s enthusiasm and participation, and we’re already looking forward to welcoming you again next year. See you then!

M5Stack Open Day 2024

Time flies, and 2023 has come to an end. M5Stack's products and services have accompanied users worldwide throughout the year. 2023 was a year of continuous innovation for M5Stack, with 76 new products released at a rate of one per week. As we set sail for 2024, let's look back at the brilliance of the past year and unveil the top 10 best-selling products of 2023!

 1. ATOM LITE

Once again, Atom Lite tops this year's list of best-selling products, following on from last year's success. Launched in 2020, Atom Lite's outstanding features and enduring vitality have won over a wide range of users worldwide.

Atom Lite user case @Peter Neufeld

Atom Lite is a compact development board, measuring only 24 * 24mm, which provides more GPIO pins for users to customize freely. It is particularly suitable for embedded smart hardware development.

This development board uses the ESP32-PICO-D4 solution as the main controller, integrating Wi-Fi module and built-in 3D antenna. It has 4MB of SPI flash memory, as well as Infra-Red (IR) infrared, RGB LED, buttons, and GROVE/HY2.0 interfaces. Additionally, the onboard Type-C interface enables fast program uploading and downloading, and there is an M2 screw hole on the back for fixation.

2. ATOM ECHO

Also released in 2020, Atom Echo has undoubtedly become a dark horse product this year. In 2023, with the power of Home Assistant and ChatGPT, the Atom Echo has sold out again and again. The ability to connect to ChatGPT, act as a personal voice assistant with customisable wake words, and do it all for just $13 makes it a must-have smart home device.

Atom Echo voice assistant use case @Home Assistant

Atom Echo is a programmable smart speaker. Despite its small size of only 24 * 24 * 17mm, it boasts impressive functionality. With the built-in wireless capabilities of the ESP32, it can easily connect to devices such as smartphones and tablets for seamless music playback. It can also stream specified media music via Wi-Fi.

To facilitate voice functionality, Atom Echo integrates an STT (Speech-to-Text) service internally. Users only need to burn specified firmware to enable this feature and perform various operations through voice commands. Users can also write code to integrate Atom Echo with cloud platforms like AWS and Google, utilizing the built-in microphone and speaker for voice interaction, enabling certain AI capabilities, such as voice control, intelligent conversations, and IoT functionalities.

The speaker has a built-in RGB LED (SK6812) that visually displays the connection status. In addition to being used as a smart speaker, it still retains the control capabilities of the ATOM series and can be connected to external devices via the GROVE interface. The M2 screw hole on the back facilitates secure installation.

3. M5STICKC PLUS

M5StickC Plus is a powerful, portable and expandable development board. Since its release in 2020, it has consistently been at the top of various best-seller lists. At the end of 2022, we welcomed M5StickC Plus2 and officially said goodbye to M5StickC Plus.

M5StickC Plus is a powerful microcontroller module that is compact and easy to carry. Despite its small size, M5StickC Plus integrates rich hardware resources, including infrared, RTC, microphone, LED, IMU, buttons, buzzers, and PMU.

M5StickC Plus is equipped with the ESP32-PICO-D4 processor, providing powerful computing and communication capabilities. It features a 1.14-inch color TFT display that can show images, text, and user interfaces, offering a good interactive experience. Additionally, M5StickC Plus has a built-in battery for standalone use, eliminating the need for an external power source.

The module is equipped with various sensors, including an accelerometer, gyroscope, and magnetometer, enabling it to sense and measure object motion and environmental conditions. It also has Wi-Fi and Bluetooth connectivity, allowing data transmission and remote control with other devices. The interface supports HAT and Unit series products. This compact and exquisite development tool inspires endless creative possibilities.

4. M5CORE2

M5Core2 is the second-generation host of the M5Stack Core series, featuring an ESP32 chip and a touchscreen. It is known for its easy stacking, expandability, and rapid development capabilities. Since its release in 2020, Core2 has consistently been a hot seller in both domestic and international markets, loved by a large number of users. Amazon Web Services (AWS) and M5Stack have collaborated to launch Core2 for AWS. Now, we have the Core2 V1.1 version.

M5Core2 is a versatile development kit with a 2-inch IPS touchscreen display. It is built around the ESP32 microcontroller, which provides Wi-Fi and Bluetooth connectivity. The Core2 module offers a variety of built-in features, including an accelerometer, gyroscope, magnetometer, speaker, microphone, and more.

The development kit supports UIFlow, a graphical programming interface, as well as Arduino and MicroPython. This allows users to choose their preferred programming language and easily develop applications. The modular design of M5Core2 enables stacking of additional modules, called Units, on top of the base module, expanding its capabilities and creating custom projects.

M5Core2 also includes a built-in 390mAh battery, enabling portable and standalone use. It has a USB Type-C interface for charging and programming, as well as an SD card slot for extended storage.

5. ULTRASONIC I2C Unit

Ultrasonic I2C Unit is an ultrasonic ranging sensor with an I2C communication interface. The hardware features the RCWL-9620 ultrasonic ranging chip paired with a 16mm probe, enabling precise ranging within a range of 2cm to 450cm (with an accuracy of ±2%). As an I2C slave device, the sensor can share the bus resources with other I2C devices, allowing for efficient use of IO pins. It is ideal for applications such as obstacle avoidance in robots and liquid-level detection.

 

6. ENVIII Unit

ENV III is an environmental sensor that integrates the SHT30 and QMP6988 sensors, used for detecting temperature, humidity, and atmospheric pressure data. The SHT30 is a high-precision, low-power digital temperature and humidity sensor that supports the I2C interface (SHT30: 0x44, QMP6988: 0x70). The QMP6988 is an absolute pressure sensor designed for mobile applications, known for its high accuracy and stability, making it suitable for environmental data collection and monitoring projects.

 

7. AtomS3

AtomS3 is a highly integrated programmable controller based on the ESP32-S3 main controller. It features an ESP32-S3 main controller with built-in Wi-Fi capability and an 8M onboard flash memory. The controller also includes a 0.85-inch IPS screen with programmable buttons below it. Additionally, it is equipped with a 5V to 3.3V circuit, a 6-axis gyroscope sensor (MPU6886), an onboard Type-C interface (for power and firmware download), an HY2.0-4P expansion port, and six GPIO pins and power pins reserved at the bottom for easy expansion of various applications.

With a product size of only 24x24x13mm, the AtomS3 is perfect for various embedded smart device applications. It provides powerful functionality and flexible expandability, making it suitable for developing a wide range of embedded systems and smart devices.

8. PIR Motion Unit

PIR Motion Unit is a human infrared sensor unit. It belongs to the "passive infrared detector" category and works by detecting the infrared radiation emitted or reflected by humans or objects. When infrared radiation is detected, it outputs a high-level signal and maintains a delay for a certain period (keeping the signal high and allowing for repeated triggering) until the trigger signal disappears (returns to a low level). The PIR Motion Unit is suitable for various applications that require detecting human activity and motion, including security, automation, energy management, and people counting.

9. BASIC V2.7

Basic is the first-generation host of M5Stack, offering high cost-effectiveness and a rich collection of case resources. Through continuous optimization and development, it has now iterated to the V2.7 version.

Basic V2.7 features a 2.0-inch color TFT LCD screen with a resolution of 320x240, which can display graphical interfaces and text information. It is also equipped with three programmable buttons, a programmable touchscreen, a speaker, and a set of expansion pins to support the connection and expansion of various peripheral devices.

This development board uses the ESP32 Internet of Things chip, integrates Wi-Fi capability, and has 16MB of SPI flash memory. As a low-power dual-core processor, it performs exceptionally well in various application scenarios.

10. ATOM U

ATOM U is a compact and flexible Internet of Things voice recognition development board. It uses the Espressif ESP32 main control chip with two low-power Xtensa® 32-bit LX6 microprocessors, operating at a high frequency of up to 240MHz. ATOM U integrates USB-A interface, IR emitter, and programmable LED lights, allowing for plug-and-play convenience for program uploading, downloading, and debugging. It also includes a Wi-Fi module and a built-in digital microphone (SPM1423 PDM) for clear audio recording, making it suitable for various IoT human-machine interaction and speech-to-text (STT) input recognition scenarios.

ATOM U supports low-code development and provides features such as UIFlow graphical programming platform, script programming, no-compilation execution, and cloud pushing. It is fully compatible with mainstream development platforms such as Arduino and ESP32-IDF.

ATOM U has a high level of integration, including USB-A programming/power interface, IR emitter, programmable RGB light, and buttons. The professionally tuned RF circuit ensures stable and reliable wireless communication quality.

M5Stack's success is inextricably linked to our community's support, and we thank you for it. We wish you a Happy New Year! We will continue to provide more and better services to meet your needs in the coming year.