Flash an AirGradient ONE from the Command Line

Michael Lynch

커맨드 라인으로 AirGradient ONE 플래시하기

집 안 공기질을 측정하려고 AirGradient ONE 실내 공기질 측정기를 두 대 구매했습니다. AirGradient 기기는 오픈소스라서 AirGradient의 독점 클라우드 대시보드로 데이터를 보내지 않고도 직접 만든 커스텀 펌웨어를 올리고 공기질 데이터를 로컬에서 수집할 수 있습니다.

사무실에 AirGradient ONE 공기질 측정기를 두고 CO2와 오염 물질을 측정하고 있습니다.

기존 펌웨어 플래시 문서는 Arduino IDE라는 투박한 GUI 프로그램을 사용해야 합니다:

AirGradient ONE을 플래시하는 기존 가이드는 투박한 GUI 프로그램인 Arduino IDE에 의존합니다.

커맨드 라인으로 AirGradient 기기를 플래시하는 방법을 찾을 수 없었고, 알아내는 데 몇 시간이 걸렸습니다. 그래서 아래에 과정을 정리했습니다.

여담: AirGradient가 그렇게까지 화제가 되는지 모르겠습니다

포럼에서 AirGradient 이야기가 나올 때마다 다들 제품에 열광하는 분위기입니다. 제가 써 본 AirGradient ONE은 그저 그렇습니다. 소프트웨어는 버그가 굉장히 많고 문서도 빈약합니다. 하지만 완제품 공기질 측정기 중 오픈소스인 제품을 파는 곳은 AirGradient밖에 찾지 못해서 결국 두 번째 기기를 또 구매했습니다.

수년간 AirGradient는 AirGradient ONE에 소프트웨어를 올리는 방법을 따로 공개하지 않았습니다. 저는 아래 블로그 글들을 보고 방법을 익혔습니다:

올해 들어서야 AirGradient가 공식 플래시 가이드를 공개했지만, 여전히 찾기가 다소 어렵습니다.

환경

이 과정은 Debian 13.0에서 테스트했지만, Debian/Ubuntu 계열 시스템이라면 어디서든 동작해야 합니다.

패키지 설치

먼저 필요한 기본 패키지를 설치합니다:

sudo apt update && \
  sudo apt install -y \
    git \
    curl \
    python3 \
    python3-serial

arduino-cli 설치

다음으로 Arduino CLI 도구를 설치합니다:

ARDUINO_CLI_VERSION='1.2.2'
ARDUINO_BIN_DIR="${HOME}/.local/arduino-cli"

mkdir -p "${ARDUINO_BIN_DIR}" && \
  curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh \
  | BINDIR="${ARDUINO_BIN_DIR}" sh -s "${ARDUINO_CLI_VERSION}"
export PATH="${PATH}:${ARDUINO_BIN_DIR}"

설치가 제대로 됐는지 확인하려고 arduino-cli 버전 문자열을 출력합니다:

$ arduino-cli version
arduino-cli  Version: 1.2.2 Commit: c11b9dd5 Date: 2025-04-22T13:51:01Z

ESP32 라이브러리 다운로드

AirGradient ONE은 ESP32 Arduino 라이브러리에 의존합니다. 이 글을 쓰는 시점 기준으로 AirGradient는 아직 Arduino 3.x 버전과 호환되지 않으므로, 최신 안정 버전인 2.x를 사용해야 합니다.

ARDUINO_ESP32_VERSION='2.0.17'

arduino-cli config init \
  --additional-urls https://espressif.github.io/arduino-esp32/package_esp32_index.json && \
  arduino-cli core install "esp32:esp32@${ARDUINO_ESP32_VERSION}"

내 기기의 경로 찾기

다음으로 AirGradient ONE의 기기 경로가 필요합니다. 기기 경로를 찾는 가장 간단한 방법은 다음과 같습니다:

  1. dmesg --follow 실행
  2. AirGradient ONE을 USB로 시스템에 연결
  3. dmesg 출력에서 기기 경로가 나타나는지 확인

제 시스템에서는 이렇게 표시됩니다:

$ sudo dmesg --follow
[517021.978880] usb 1-4: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.01
[517021.978884] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[517021.978894] usb 1-4: Product: USB JTAG/serial debug unit
[517021.978896] usb 1-4: Manufacturer: Espressif
[517021.978898] usb 1-4: SerialNumber: D8:3B:DA:1A:EE:C4
[517022.017678] cdc_acm 1-4:1.0: ttyACM0: USB ACM device
                                 ^^^^^^^
                                 Path name

이 출력 결과를 보면 제 시스템에서 AirGradient ONE 경로는 /dev/ttyACM0입니다:

AIRGRADIENT_PATH='/dev/ttyACM0'

기기 경로에 쓰기 권한 부여

다음으로 AirGradient 파일 경로에 쓸 수 있는지 확인합니다:

sudo chmod a+rw "${AIRGRADIENT_PATH}"

이제 AirGradient 경로는 다음과 같은 권한을 가져야 합니다:

$ ls -l "${AIRGRADIENT_PATH}"
crw-rw-rw- 1 root dialout 166, 0 Aug 10 10:34 /dev/ttyACM0
 ^^^^^^^^

그리고 dialout 그룹에 제 계정을 추가해 해당 경로에 쓸 수 있도록 합니다:

sudo adduser "$(whoami)" dialout

AirGradient 소스 가져오기

다음으로 AirGradient 공장 출하 플래시 페이지에서 최신 프로덕션 릴리스를 확인합니다.

# Current production release, as of this writing.
AIRGRADIENT_RELEASE='3.3.8'

경고: AirGradient 웹사이트에 나온 최신 버전은 AirGradient GitHub 저장소의 최신 릴리스 태그와 일치하지 않습니다. 제가 3.3.9를 테스트했을 때는 두 기기 모두 CO2와 온도 측정에 실패해서, 3.3.9가 알려진 버그가 있는 릴리스인지는 잘 모르겠습니다.

버전 번호를 확인했으니 AirGradient GitHub 저장소에서 AirGradient 소스 코드를 가져옵니다:

git clone --recurse-submodules \
  --branch "${AIRGRADIENT_RELEASE}" \
  --depth 1 \
  https://github.com/airgradienthq/arduino.git \
  ~/airgradient-one

AirGradient ONE 기기에 펌웨어 플래시하기

이제 기기에 소프트웨어를 플래시할 차례입니다:

cd ~/airgradient-one && \
  arduino-cli compile \
    --verbose \
    --fqbn esp32:esp32:esp32c3:CDCOnBoot=cdc,PartitionScheme=min_spiffs,DebugLevel=info \
    --library . \
    --port "${AIRGRADIENT_PATH}" \
    --verify \
    --upload \
    examples/OneOpenAir/OneOpenAir.ino

참고: AirGradient ONE 기기의 영구 데이터(즉, 설정 데이터를 포함한 하드 리셋)를 지우려면 --fqbn 플래그 끝에 ,EraseFlash=all을 추가하세요.

플래시가 성공하면 기기가 재부팅되고 과정이 끝날 때 다음과 같은 출력이 표시됩니다:

Wrote 1753792 bytes (967231 compressed) at 0x00010000 in 14.7 seconds (effective 952.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

선택 사항: 시리얼 로그 출력 보기

AirGradient가 컴퓨터에 연결된 상태에서 arduino-cli monitor 명령으로 시리얼 포트를 통해 로그 출력을 볼 수 있습니다:

$ arduino-cli monitor --port "${AIRGRADIENT_PATH}"
Using default monitor configuration for board: esp32:esp32:heltec_wifi_kit_32_V3
Monitor port settings:
  baudrate=9600
  bits=8
  dtr=on
  parity=none
  rts=on
  stop_bits=1

Connecting to /dev/ttyACM0. Press CTRL-C to exit.
[1] Standard Particle PM 2.5 = 7.00 ug/m3
[1] Particle Count 0.3 = 1298.5
[1] Particle Count 0.5 = 383.5
[1] Particle Count 1.0 = 39.7
[1] Particle Count 2.5 = 2.0
[1] Particle Count 5.0 = 2.0
[1] Particle Count 10 = 0.0

대안: Nix flake

Nix를 즐겨 쓴다면 Nix 방식으로 처리하고 싶을 수도 있습니다. 위의 모든 과정을 자동화하는 Nix flake를 만들어 두었습니다:

저장소를 플래시하고 싶을 때는 다음 명령만 실행하면 됩니다:

nix run .#flash

시리얼 출력을 보고 싶을 때는 다음 명령을 실행합니다:

nix run .#monitor

제 Nix flake가 다른 시스템에서 얼마나 잘 동작할지는 확신할 수 없으므로, 시스템에 맞게 조금 손봐야 할 수도 있습니다.

결론

이 가이드가 AirGradient ONE 기기를 플래시하고 원하는 대로 펌웨어를 커스텀하는 데 도움이 되길 바랍니다.

원문은 Michael Lynch님이 에 게재했습니다.

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.