IoT Core에 등록한 라즈베리파이와 AWS IoT 간의 MQTT 통신 (feat. 초음파 거리 측정 센서)

2024. 5. 21. 18:56AWS

지난 포스팅에서 IoT Core에 라즈베리파이를 등록하고 보안 규칙을 설정하는 방법에 대해 알아보았다. 이번 포스팅에서는 먼저 간단한 코드로 MQTT 통신을 테스트한다. 이어서 라즈베리파이가 초음파 거리 측정 센서 데이터 Publish하면 AWS IoT Core가 Subscribe 하는 것을 구현한다.

MQTT 통신 테스트

먼저 라즈베리파이에 mqtt 모듈을 설치한다.

npm install mqtt -save

 

설정 페이지에서 디바이스 엔드포인트를 복사한다. 이 값은 MQTT 통신 테스트용 코드에 사용할 부분이 있다.

 

MQTT 테스트 클라이언트 페이지에 접속한다. 토픽의 이름을 작성하고, 구독 버튼을 클릭한다.

 

라즈베리파이에서 아래 명령어로 테스트용 코드를 실행하였다. 콘솔에 Connected! 가 출력되고, AWS IoT Core에서 새로운 JSON 데이터들이 Subscribe 된다면 성공이다.

sudo node IoTCorePubSubTest.js
const mqtt = require('mqtt');
const fs = require('fs');
const path = require('path');

// File paths
const ENDPOINT = "{설정 페이지에서 복사한 디바이스 엔드포인트}";
const THING_NAME = 'raspberrypi';  // device name
const CERTPATH = "/home/team6/pi-ultrasound/raspberrypi.cert.pem"; // cert file path
const KEYPATH = "/home/team6/pi-ultrasound/raspberrypi.private.key"; // key file path
const CAROOTPATH = "/home/team6/pi-ultrasound/root-CA.crt"; // RootCaPem file path
const TOPIC = 'test'; // topic name

// MQTT client options
const options = {
    clientId: THING_NAME,
    cert: fs.readFileSync(CERTPATH),
    key: fs.readFileSync(KEYPATH),
    ca: fs.readFileSync(CAROOTPATH),
    rejectUnauthorized: true,
    protocol: 'mqtts'
  };
  
// Connect to the MQTT broker
const client = mqtt.connect(`mqtts://${ENDPOINT}:8883`, options);

client.on('connect', () => {
console.log('connected!!');

let i = 0;
setInterval(() => {
    const payload = JSON.stringify({ action: i * 0.1 }); 
    client.publish(TOPIC, payload, { qos: 1 });
    i += 1;
}, 2000);
});

client.on('error', (error) => {
    console.error('Connection error:', error);
});

process.on('SIGINT', () => {
    client.end(() => {
        console.log('Disconnected from MQTT broker');
        process.exit(0);
    });
});

 

라즈베리파이 - 초음파 거리 측정 센서의 회로

다음과 같이 라즈베리파이, 초음파 센서, 브레드보드, 점퍼선 4개로 회로를 구성하였다.

초음파 거리 측정 센서 데이터 MQTT 통신

먼저 GPIO 핀 관련 모듈을 설치한다.

npm install pigpio

 

라즈베리파이에서 아래 명령어로 코드를 실행하였다. node.js로 작성한 MQTT 통신 및 초음파 거리 측정 코드에 대해 간단히 정리하겠다. 

  • 먼저 필요한 라이브러리들을 임포트한다. IoTCore 디바이스 엔드포인트와 디바이스명을 작성해야 한다. 디바이스 등록 단계에서 설치했던 cert 파일, key 파일, RootCaPem 파일 경로도 작성한다. 이 경로들로 MQTT 클라이언트 옵션을 지정한다.
  • MQTT 브로커 연결, Input/Output 핀 지정, Block Scope의 startTime과 endTime let 변수 선언을 한다. 초음파를 send할 때 startTime을 저장하고, 초음파를 detect 했을 때 endTime을 저장한다.
  • 초음파의 이동 시간과 속도를 이용하여 2가지 방식으로 물체와의 거리를 계산한다. 거리 측정의 정확도 체크를 위하여 2가지 방식을 사용했다.
  • JSON 형태로 payload에 데이터를 저장하고, 토픽에 payload를 publish 한다. 2초마다 거리를 측정하는 함수를 콜백 함수로 실행시킨다.
  • SIGINT(Ctrl+C) 신호가 들어오면 프로세스를 종료한다.
sudo node IoTCoreDistMqtt.js
const mqtt = require('mqtt');
const fs = require('fs');
const Gpio = require('pigpio').Gpio; 

// Pin numbers of Ultrasound sensor
const TRIGER = 24;
const ECHO = 23;

// IoT Core Auth File path
const ENDPOINT = "{설정 페이지에서 복사한 디바이스 엔드포인트}";  // Endpoint
const THING_NAME = 'raspberrypi';  // Device name
const CERTPATH = "/home/team6/pi-ultrasound/raspberrypi.cert.pem"; // cert file path
const KEYPATH = "/home/team6/pi-ultrasound/raspberrypi.private.key"; // key file path
const CAROOTPATH = "/home/team6/pi-ultrasound/root-CA.crt"; // RootCaPem file path
const TOPIC = 'distance_from_obj';  // Topic name

// MQTT client options
const options = {
    clientId: THING_NAME,
    cert: fs.readFileSync(CERTPATH),
    key: fs.readFileSync(KEYPATH),
    ca: fs.readFileSync(CAROOTPATH),
    rejectUnauthorized: true,
    protocol: 'mqtts'
};

// Connect to the MQTT broker
const client = mqtt.connect(`mqtts://${ENDPOINT}:8883`, options);

// Output & Input pin
const trig = new Gpio(TRIGER, { mode: Gpio.OUTPUT });
const echo = new Gpio(ECHO, { mode: Gpio.INPUT, alert: true });

// Ensure trigger is low (Initializing sensor)
trig.digitalWrite(0);

// Block scoped variable
let startTime;
let endTime;

/* 
Event handler of an ultrasound sensor
level: Event level of ultrasound sensor 
(1: send ultrasound / 0: detect reflected ultrasound)
tick: Time when event occurred
*/
echo.on('alert', (level, tick) => {
    if (level === 1) {
        startTime = tick;
    } else if (level === 0) {
        endTime = tick;

        const period = endTime - startTime;
        // Measure distance in two ways
        const dist1 = Math.round(period / 58 * 100) / 100; // dist1 계산
        const dist2 = Math.round(period * 17241 / 1000000 * 100) / 100; // dist2 계산

        // Write MQTT message
        const payload = JSON.stringify({ dist1: dist1, dist2: dist2 });

        /* 
        Publish MQTT message
        Param: topic, message(payload), quality of service(qos)
        */
        client.publish(TOPIC, payload, { qos: 1 });

        console.log("Dist1", dist1, "cm", ", Dist2", dist2, "cm");

        if (dist1 < 10 && dist2 < 10) {
            console.log("detect");
        }
    }
});

// Setting the pulse trigger cycle
const measureDistance = () => {
    trig.trigger(10, 1); // Send a 10µs pulse
};

// Measure distance every 2 seconds
const interval = setInterval(measureDistance, 2000);

// Exit process handler (SIGINT: Ctrl + C)
process.on('SIGINT', () => {
    clearInterval(interval);
    trig.digitalWrite(0);
    client.end(() => {
        console.log('Disconnected from MQTT broker');
        process.exit(0);
    });
});

 

아래 영상은 라즈베리파이에서 초음파 거리 측정 센서의 데이터를 Publish하고, 실시간으로  MQTT 테스트 클라이언트에서 Subscribe하는 것을 촬영한 것이다.

 

*참고 사이트

https://blueberry-kyu.tistory.com/m/17