성능지표 테스트

2023. 1. 10. 15:06개발/Arduino

그동안 성능지표 테스트를 준비했다.

중소벤처기업부 에서 진행하는 과제에 선정돼서

연구비를 받아 진행하는데

 

그 과정에서 어떤 식으로 기술을 연구/개발 하는지

지표에 맞게 테스트를 진행한다.

위와 같이 5가지 항목이 있다.

각 항목별로 어떤 식으로 진행할지 검토하고

서류를 작성한다.

이런 식으로 서류를 작성했다.

 

아무튼 전반적인 준비 과정을 기록한다.


모든 센서 데이터는 local Node-red 에서

MQTT 통신으로 수신받는다.

 

2023.01.04 - [기록/개발 노트] - 성능지표 및 Arduino 함수 트리거 처리

 

성능지표 및 Arduino 함수 트리거 처리

https://www.mss.go.kr/site/smba/main.do 중소벤처기업부 중소기업중앙회 등 기관 중소기업 조사, 통계 DB화 검색, 내려받기 등 제공. www.mss.go.kr 중소벤처기업부 에서 매년 'R&D 역량제고사업 맞춤형기술파

iruk.tistory.com

이전에 레이다 센서에 관한 내용을 기록했었다.

레이다 센서 말고도 3가지 센서를 추가했다.

 

1. 암모니아 센서

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

const char* ssid = ""; // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* password = "";  // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* mqtt_server = ""; //브로커 주소
const char* outTopic = ""; // 이름이 중복되지 않게 설정 기록
const char* inTopic = ""; // 이름이 중복되지 않게 설정 기록
const char* clientName = "";  // setup 함수에서 자동생성


WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];

//json을 위한 설정
StaticJsonDocument<200> doc;
DeserializationError error;
JsonObject root;

int Vpin = A0; 
int Vvalue = 0;
String sMac="";
char mac[20];
unsigned long previousMillis = 0;     
const long interval = 1800000;

void setup_wifi() {
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

// 통신에서 문자가 들어오면 이 함수의 payload 배열에 저장된다.
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  deserializeJson(doc,payload);
  root = doc.as<JsonObject>();
}
// mqtt 통신에 지속적으로 접속한다.
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientName)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish(outTopic, "Reconnected");
      // ... and resubscribe
      client.subscribe(inTopic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(9600);
  setup_wifi();

  //이름 자동으로 생성
  Serial.print("Mac address :  ");
  uint8_t macH[6]="";
  WiFi.macAddress(macH);
  sprintf(mac,"%02x%02x%02x%02x%02x%02x%c",macH[0], macH[1], macH[2], macH[3], macH[4], macH[5],0);
  sMac=mac;
  clientName=mac;
  Serial.println(mac);

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
    doTick();
      if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

void doTick() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    sensor();
  }  
}
void sensor() {
  
  Vvalue = analogRead(Vpin);
  Serial.println(Vvalue);
  
  doc["mac"] = sMac;
  doc["amonia"] = Vvalue;
  char jsonBuffer[512];
  serializeJson(doc, jsonBuffer);
  client.publish(outTopic, jsonBuffer);
}

2. 미세먼지 센서

//1-16-3 https://youtu.be/6rfDrpsOGMY 를 기초로 작업
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "PMS.h"

// 아래의 6개설정은 사용자 환경에 맞게 수정하세요.
const char* ssid = ""; // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* password = "";  // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* mqtt_server = ""; //브로커 주소
const char* outTopic = ""; // 이름이 중복되지 않게 설정 기록
const char* inTopic = ""; // 이름이 중복되지 않게 설정 기록
const char* clientName = "";  // setup 함수에서 자동생성

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];

//json을 위한 설정
StaticJsonDocument<200> doc;
DeserializationError error;
JsonObject root;

//PMS5003 센서를 위한 변수
PMS pms(Serial2);
PMS::DATA data;

int dustValue;
String sMac="";
char mac[20];
unsigned long previousMillis = 0;     
const long interval = 1800000;

void setup_wifi() {
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

// 통신에서 문자가 들어오면 이 함수의 payload 배열에 저장된다.
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  deserializeJson(doc,payload);
  root = doc.as<JsonObject>();
  //red = root["r"];
}

// mqtt 통신에 지속적으로 접속한다.
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientName)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish(outTopic, "Reconnected");
      // ... and resubscribe
      client.subscribe(inTopic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  setup_wifi();

  //이름 자동으로 생성
  Serial.print("Mac address :  ");
  uint8_t macH[6]="";
  WiFi.macAddress(macH);
  sprintf(mac,"%02x%02x%02x%02x%02x%02x%c",macH[0], macH[1], macH[2], macH[3], macH[4], macH[5],0);
  sMac=mac;
  clientName=mac;
  Serial.println(mac);

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  if (pms.read(data)){
  doTick();
  }
  
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

}

void doTick() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    sensor(); // 오존 센서
  }  
}

void sensor() {
  
  dustValue=data.PM_AE_UG_2_5;
  Serial.print("PM 2.5 (ug/m3): ");
  Serial.println(dustValue);
  
  doc["mac"] = sMac;
  doc["dust"] = dustValue;
  char jsonBuffer[512];
  serializeJson(doc, jsonBuffer);
  client.publish(outTopic, jsonBuffer);
}

3. 레이다 센서

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

#define RCWL D6 //레이다

// 아래의 6개설정은 사용자 환경에 맞게 수정하세요.
const char* ssid = ""; // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* password = "";  // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* mqtt_server = ""; //브로커 주소
const char* outTopic = ""; // 이름이 중복되지 않게 설정 기록
const char* inTopic = ""; // 이름이 중복되지 않게 설정 기록
const char* clientName = "";  // setup 함수에서 자동생성

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];

//json을 위한 설정
StaticJsonDocument<200> doc;
DeserializationError error;
JsonObject root;

char mac[20];
String sMac="";
String inputString;
int sensor,preSensor,counter;
unsigned long previousMillis = 0;     
const long interval = 1000;

void setup_wifi() {
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

// 통신에서 문자가 들어오면 이 함수의 payload 배열에 저장된다.
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  deserializeJson(doc,payload);
  root = doc.as<JsonObject>();
}

// mqtt 통신에 지속적으로 접속한다.
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientName)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      //client.publish(outTopic, "Reconnected");
      // ... and resubscribe
      client.subscribe(inTopic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void doTick() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    detect(); // 레이다 센서
  }  
}

void detect(){
 sensor = digitalRead(RCWL);

  if(preSensor==0 && sensor==1){ // 새로운 감지 발생 시
    if(counter==0){
      digitalWrite(D7,HIGH); // 릴레이 on
      Serial.println("detected! relay On ");
      counter++;
      
      StaticJsonDocument<200> doc;
      doc["mac"] = sMac;
      doc["detect"] = "on";
      char jsonBuffer[512];
      serializeJson(doc, jsonBuffer); // print to client
      Serial.println(jsonBuffer);
      client.publish(outTopic, jsonBuffer);
    }
    else if(counter==1){
      digitalWrite(D7,LOW); // 릴레이 off
      Serial.println("detected! relay Off ");
      counter=0;
      
      StaticJsonDocument<200> doc;
      doc["mac"] = sMac;
      doc["detect"] = "off";
      char jsonBuffer[512];
      serializeJson(doc, jsonBuffer); // print to client
      Serial.println(jsonBuffer);
      client.publish(outTopic, jsonBuffer);
    } 
  }
  
  else{
    Serial.println("waiting...");
  }

  preSensor=sensor;
}

void setup() {
  Serial.begin(115200);
  pinMode(RCWL,INPUT);
  pinMode(D7, OUTPUT);
  digitalWrite(D7,0);

  Serial.println("mac address");
  uint8_t macH[6]="";
  WiFi.macAddress(macH);
  sprintf(mac,"%02x%02x%02x%02x%02x%02x%c",macH[0], macH[1], macH[2], macH[3], macH[4], macH[5],0);
  sMac=mac;
  clientName=mac;
  Serial.println(clientName);
  
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  doTick();
  
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

4. 오존 센서

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <MQ131.h>

#define mq131 A0 // 오존감지

// 아래의 6개설정은 사용자 환경에 맞게 수정하세요.
const char* ssid = ""; // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* password = "";  // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* mqtt_server = ""; //브로커 주소
const char* outTopic = ""; // 이름이 중복되지 않게 설정 기록
const char* inTopic = ""; // 이름이 중복되지 않게 설정 기록
const char* clientName = "";  // setup 함수에서 자동생성

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];

//json을 위한 설정
StaticJsonDocument<200> doc;
DeserializationError error;
JsonObject root;

char mac[20];
String sMac="";
float o3value;
int tect;
unsigned long previousMillis = 0;     
const long interval = 1000;

void setup_wifi() {
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

// 통신에서 문자가 들어오면 이 함수의 payload 배열에 저장된다.
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  deserializeJson(doc,payload);
  root = doc.as<JsonObject>();
}

// mqtt 통신에 지속적으로 접속한다.
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientName)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish(outTopic, "Reconnected");
      // ... and resubscribe
      client.subscribe(inTopic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void doTick() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    sensor(); // 오존 센서
  }  
}

void sensor() {
  Serial.println("Sampling...");
  MQ131.sample();
  float o3value = MQ131.getO3(PPM);

  reconnect(); // sampling 하는동안 MQTT 종료됨
  
  StaticJsonDocument<200> doc;
  doc["mac"] = sMac;
  doc["o3"] = o3value;
  char jsonBuffer[512];
  serializeJson(doc, jsonBuffer); // print to client
  Serial.println(jsonBuffer);
  client.publish(outTopic, jsonBuffer);
}

void setup() {
  Serial.begin(115200);
  
  Serial.println("mac address");
  uint8_t macH[6]="";
  WiFi.macAddress(macH);
  sprintf(mac,"%02x%02x%02x%02x%02x%02x%c",macH[0], macH[1], macH[2], macH[3], macH[4], macH[5],0);
  sMac=mac;
  clientName=mac;
  Serial.println(clientName);
  
  setup_wifi();
  
  Serial.println("Wait for calibration...");
  MQ131.begin(2,A0, LOW_CONCENTRATION, 1000000);
  MQ131.calibrate();
  Serial.println("calibration done");
  
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  doTick();
 
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
   
}

소스는 위와 같다.

전부 다 같은 MQTT 서버, 같은 MQTT 토픽에 데이터를 전송한다.

 

var time = new Date().toLocaleString('ko-KR',
    { timeZone: 'Asia/Seoul' });

var ammonia = msg.payload.amonia;
var newMsg = {};

newMsg.collection = '1_ammoniaSensor';
newMsg.operation = 'insert';
newMsg.payload = { 'mac':msg.payload.mac, 'ammonia': ammonia, 'time': time };
newMsg.projection = { 'start': 1, '_id': 0 };
return newMsg;

그 뒤 Node-red 에서

데이터를 mongoDB 에 저장한다.

 

센서별로 1, 2, 3, 4 숫자를 collection에서 구분해

보기에 편하도록 했다.

위와 같이 mongoDB 에서

편하게 볼 수 있도록 설정했다.

 

근데 문제는

성능지표를 보면

암모니아, 미세먼지 센서는

3일간 측정해야한다.

현재는 CPU와 센서를

노트북에 USB로 연결해서 전원을 해결했는데

 

3일간 하루종일 구동하려면

외부 전원이 필요하다

그래서 위 사진처럼

콘센트에 전원을 연결해서

연구실에 3일동안 켜 놓을 생각이다.

 

그리고 현재 1초마다 센서값을 받아오도록 했는데

30분마다 한 번씩 받아오도록 소스를 수정했다.

//const long interval = 1000;
const long interval = 1800000;

위와 같이 interval 변수를 수정했다.

 

또한, Node-red 도 local환경이기 때문에

노트북이 꺼지면 돌아가지 않는다.

 

따라서 AWS Instance 가상서버를 사용해

24시간 서버를 돌리고

그 안에 설치된 Node-red와 mongoDB에서

프로그램이 돌아가도록 했다.


그리고 성능지표 항목 중에서

세번째, IoT 제어 통신응답 정확성은

위와 같이 Node-red에서 웹사이트를 구성해 테스트했다.

위 보드에 전원이 입력되면

자동으로 AWS 서버와 연결돼

MQTT로 정보를 송신하고

 

웹에 버튼이 자동생성되며

실시간으로 웹과 연동된다.

 

성능지표 테스트 준비 끝

'개발 > Arduino' 카테고리의 다른 글

Xiaomi Flower care + ESP32 / BLE통신  (0) 2023.03.13
Lora 및 485 통신  (0) 2023.03.08
ESP32 BLE & RS-232 RS-485통신  (0) 2023.03.02
ESP32 web server  (0) 2023.02.28
성능지표 및 Arduino 함수 트리거 처리  (2) 2023.01.04