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

2023. 1. 4. 15:00개발/Arduino

https://www.mss.go.kr/site/smba/main.do

 

중소벤처기업부

중소기업중앙회 등 기관 중소기업 조사, 통계 DB화 검색, 내려받기 등 제공.

www.mss.go.kr

중소벤처기업부 에서 매년

'R&D 역량제고사업 맞춤형기술파트너' 를 실시한다.

현재 PTC 난방기 프로젝트가 작년 6월에 해당 정책에 선정되어서

국가의 지원을 받아 진행 중인 상태다.

 

매달 연구를 진행하면서

연구노트를 작성하고

그에 맞는 견적서, 명세표 및

각종 서류들을 심사 받는다.

 

그 중에서도 '성능지표' 항목에 대해

오늘 테스트를 해보았다.

 

실제 그 제품이 어떤 기술적 가치를 갖는지

그 기술적 가치에 합당하는 

성능 테스트를 심사 받는 개념이다.


성능지표

5개의 항목을 작성했었다.

1,2 번은 3일간 평균값을 측정해야 하는데

공간의 제약이 있어 다음주 월요일에 진행하기로 했다.

 

3번은 준비를 마친 상태고

4번 및 5번을 테스트 하려고 한다.

검은색 제품은 '플라즈마 발생기'

간단하게 제작되어 있는 보드에는

'MQ131 오존 감지 센서' 및 

'RCWL-0516 레이다 모션 센서' 가 있다.

뭉툭하게 튀어나온 센서가 MQ 131이다.

 

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

#define RCWL D6 //레이다
#define mq131 A0 // 오존감지

// 아래의 6개설정은 사용자 환경에 맞게 수정하세요.
const char* ssid = " "; // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* password = " ";  // 와이파이 AP, 또는 스마트폰의 핫스판 이름
const char* mqtt_server = "broker.mqtt-dashboard.com"; //브로커 주소
const char* outTopic = "/khj/outTopic"; // 이름이 중복되지 않게 설정 기록
const char* inTopic = "/khj/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;
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;
    detect(); // 레이다 센서
    DoResult(); // 오존 센서
  }  
}

void detect(){
 tect = digitalRead(RCWL);
  if(tect>0){
    digitalWrite(D7,LOW);
  }
  else if(tect == 0){
    digitalWrite(D7,HIGH);
  }
}

void DoResult() {
  
  Serial.println("Sampling...");
  MQ131.sample();
  float o3value = MQ131.getO3(PPM);
  
  StaticJsonDocument<200> doc;
  doc["o3"] = o3value;
  doc["detact"] = tect;
  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();
  MQ131.begin(2,A0, LOW_CONCENTRATION, 1000000);
  MQ131.calibrate();
  pinMode(RCWL,INPUT);
  pinMode(D7, OUTPUT);
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  digitalWrite(D7,0);
}

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

위 소스코드를 사용해서 테스트해보았다.

void detect(){
 tect = digitalRead(RCWL);
  if(tect>0){
    digitalWrite(D7,LOW);
  }
  else if(tect == 0){
    digitalWrite(D7,HIGH);
  }
}

void DoResult() {
  
  Serial.println("Sampling...");
  MQ131.sample();
  float o3value = MQ131.getO3(PPM);
  
  StaticJsonDocument<200> doc;
  doc["o3"] = o3value;
  doc["detact"] = tect;
  char jsonBuffer[512];
  serializeJson(doc, jsonBuffer); // print to client
  Serial.println(jsonBuffer);
  client.publish(outTopic, jsonBuffer);
}

MQTT 데이터

void loop 문에서 위 두 함수가 반복 실행된다.

detect() 함수는 레이다 모션 센서

DoResult() 는 MQ131 센서 및 MQTT로 데이터를 출력한다.

 

문제가 하나 발생했는데

MQ131 센서는 Sampling 시간이 필요하다.

공기질을 측정하고 샘플링하는데 시간이 걸리는데

그 주기가 무려 18초다.

 

즉, detect()함수로 레이다 모션 센서를 먼저 측정해도

결국 18초 동안이나 딜레이가 걸린 상태로

MQ131센서 측정결과를 기다려야 한다.

 

RCWL-0516 레이다 모션 센서의

저조한 인식률도 문제다.

 

일단 레이다 모션 센서만 따로

동작 테스트를 해보기로 했다.


RCWL-0516 레이다 모션 센서

소스 코드에서 레이다 관련 소스만 추출했다.

#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 = "broker.mqtt-dashboard.com"; //브로커 주소
const char* outTopic = "/khj/outTopic"; // 이름이 중복되지 않게 설정 기록
const char* inTopic = "/khj/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 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;
    detect(); // 레이다 센서
  }  
}

void detect(){
 tect = digitalRead(RCWL);
  if(tect>0){
    digitalWrite(D7,LOW);
  }
  else if(tect == 0){
    digitalWrite(D7,HIGH);
  }
  
  StaticJsonDocument<200> doc;
  doc["detact"] = tect;
  char jsonBuffer[512];
  serializeJson(doc, jsonBuffer); // print to client
  Serial.println(jsonBuffer);
  client.publish(outTopic, jsonBuffer);
}

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();
   
}

출력

센서 앞에서 움직임이 있으면 1

평상시에 0 이 출력된다.

 

모션센서여서 그런지

근섭센서와는 다르게 

인식률이 낮은 느낌이다. 바로바로 변하지 않는 느낌

 

그리고 예를 들어서

위와 같이 레이다 모션 센서 앞을

특정한 물체로 가로막으면

감지가 되며 1이 출력된다.

 

근데

이 상태로 가만히 두면

몇 초 뒤에 원상태로 돌아간다( 0 출력 ).

 

그러고 나서 

다시 1이 출력된다.

 

혹시나 하고 물체를 치우고

기본 측정거리가 7m라서

센서가 벽을 바라보도록 했는데

 

1 0이 왔다갔다 출력된다.

 

센서가 예민한가..

이 오류는 앞으로 계속 생각해봐야겠다.

성능지표 4번째 항목을 보면

사람이 왔다가 떠나는 경우로 처리했다.

 

처음 감지됐을 때 1회( 사람이 화장실 사용 ),

한 번 더 감지됐을 때 1회( 사람이 떠남 )

만 전기적 신호를 내보내도록 수정한다.

 

void detect(){
 tect = digitalRead(RCWL);
  if(tect>0){
    digitalWrite(D7,LOW);
  }
  else if(tect == 0){
    digitalWrite(D7,HIGH);
  }
}

기존에는 위와 같이

tect가 0인경우 1인경우

매번 D7핀에 전기신호를 줬는데

 

이 부분을 조금 수정하려 한다.


소스 수정

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

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

  preSensor=sensor;
}

레이다 센서 값이 0->1 로 변할 때 만 동작하도록 수정했다.

preSensor 변수를 생성해 

이전에 측정된 sensor 값을 저장하고,

그 preSensor 값이 0 이고, 현재 sensor 값이 1일 때

즉, 0->1로 변했을 때만 처리를 하도록 했다.

 

0에서 1로 변했을 때

함수 안에 if문을 또 추가해서

counter 변수에 따라 동작을 구분했다.

 

초기에는 counter값이 디폴트 값 0이므로

digitalWrite HIGH 가 실행되고

counter 를 1 증가시킨다. ( counter++ )

 

다음번에 함수가 실행됐을때는

counter값이 0이 아니라 1이므로

else 문이 실행돼서 digitalWrite LOW가 실행된다.

그리고 counter를 0으로 초기화한다.

 

코드가 훨씬 깔끔하고 활용도가 높게 수정했다.

'개발 > 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
성능지표 테스트  (0) 2023.01.10