아두이노 관련 게시글이 올라오는 arduino.cc에서 project를 열심히 찾았다.
마침 친구가 지원해준 아두이노 키트가 한 개가 더 있어서 초음파 센서가 두개나 되었다.
그 덕분에 기쁜 마음으로 더 복잡한 프로젝트를 할 수 있게 되었다. 감사드린다.
Ultrasonic occupancy counter
This simple Arduino project can limit the number of people inside a shop and maintain social distancing in an automated contact free way. By harrrrrrrrrrrrrrrry.
create.arduino.cc
너로 정했다!
다음에는 라즈베리파이로 구성 된 글을 많이 올릴 듯 하다.
아두이노는 거의 2,3년 전을 끝으로 고여버린 유물들이라서 그런지 따라해보기 좋은 프로젝트가 거의 없다.
/*
This project was developed by the Design and Manufacturing Futures Lab at the University of Bristol as part of Project Clean Access
More information about the lab and the project can be found here: https://dmf-lab.co.uk/project-clean-access/
This code is for a counter to be placed in a shop entrance with separate entry and exit channels
There are detailed instructions for this project on the Instructables website:
The hardware required for this product:
2 x HC-SR04 Ultrasonic sensor
2 x 560 Ohm resistor
1 x Red LED
1 x Green LED
1 x Arduino Uno
Power supply
Correct USB cable for uploading sketch to Arduino board
Credit goes to Tim Eckel for developing the NewPing library and example sketches.
*/
#include <NewPing.h>
//Defining where the components are attached
#define TRIG_IN A1
// 입장 할 때, A1에서 트리거를 발사 할 것이다.
#define TRIG_OUT 3
// 퇴장 할 때, 3에서 트리거를 발사 할 것이다.
#define ECHO_IN A2
// 입장 할 때, A2에서 트리거를 수신 받을 것이다.
#define ECHO_OUT 4
// 퇴장 할 때, 4에서 트리거를 수신 받을 것이다.
#define LED_WAIT 12
// 이미 자리가 찼음을 의미하는 빨간색LED에는 12번 핀을 설정한다.
#define LED_ENTER 9
// 입장해도 된다고 비었음을 의미하는 초록색LED에 9번핀을 할당한다.
#define iterations 5 //Number of readings in the calibration stage
#define MAX_DISTANCE 150 // Maximum distance (in cm) for the sensors to try to read.
#define DEFAULT_DISTANCE 45 // Default distance (in cm) is only used if calibration fails.
// 교정 실패 했을 때를 위해서 사용한다.
#define MIN_DISTANCE 15 // Minimum distance (in cm) for calibrated threshold.
// 문지방을 무시하기 위한 최소거리를 설정한다.
#define MaxOccupancy 20
float calibrate_in = 0, calibrate_out = 0; // The calibration in the setup() function will set these to appropriate values.
float distance_in, distance_out; // These are the distances (in cm) that each of the Ultrasonic sensors read.
int count = 0, limit = 5; //Occupancy limit should be set here: e.g. for maximum 8 people in the shop set 'limit = 8'.
bool prev_inblocked = false, prev_outblocked = false; //These booleans record whether the entry/exit was blocked on the previous reading of the sensor.
// 불 대수를 통해서 선언한다? (불대수 예제 공부가 필요하네)
NewPing sonar[2] = { // Sensor object array.
// 초음파 센서 두 개를 사용 할 것이기 때문에 배열의 크기를 2로 선언해준다.
NewPing(TRIG_IN, ECHO_IN, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
NewPing(TRIG_OUT, ECHO_OUT, MAX_DISTANCE)
};
/*
A quick note that the sonar.ping_cm() function returns 0 (cm) if the object is out of range / nothing is detected.
We will include a test to remove these erroneous zero readings later.
*/
void setup() {
Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
// LCD로 표현하게끔 응용해봐야겠다.
pinMode(2, OUTPUT); pinMode(5, OUTPUT); pinMode(A0, OUTPUT); pinMode(A3, OUTPUT); pinMode(11, OUTPUT);
digitalWrite(2, HIGH); digitalWrite(5, LOW); digitalWrite(A0, HIGH); digitalWrite(A3, LOW); digitalWrite(11, LOW);
pinMode(LED_WAIT, OUTPUT), pinMode(LED_ENTER, OUTPUT);
digitalWrite(LED_WAIT, HIGH); digitalWrite(LED_ENTER, HIGH); //Both LEDs are lit to alert user to ongoing calibration.
Serial.println("Calibrating...");
delay(1500);
for (int a = 0; a < iterations; a++) {
delay(50);
calibrate_in += sonar[0].ping_cm();
delay(50);
calibrate_out += sonar[1].ping_cm();
delay(200);
}
calibrate_in = 0.75 * calibrate_in / iterations; //The threshold is set at 75% of the average of these readings. This should prevent the system counting people if it is knocked.
calibrate_out = 0.75 * calibrate_out / iterations;
if (calibrate_in > MAX_DISTANCE || calibrate_in < MIN_DISTANCE) { //If the calibration gave a reading outside of sensible bounds, then the default is used
calibrate_in = DEFAULT_DISTANCE;
}
if (calibrate_out > MAX_DISTANCE || calibrate_out < MIN_DISTANCE) {
calibrate_out = DEFAULT_DISTANCE;
}
Serial.print("Entry threshold set to: ");
Serial.println(calibrate_in);
Serial.print("Exit threshold set to: ");
Serial.println(calibrate_out);
digitalWrite(LED_WAIT, LOW); digitalWrite(LED_ENTER, LOW); //Both LEDs are off to alert user that calibration has finished.
delay(1000);
}
void loop() {
distance_in = sonar[0].ping_cm();
delay(40); // Wait 40 milliseconds between pings. 29ms should be the shortest delay between pings.
distance_out = sonar[1].ping_cm();
delay(40);
if (distance_in < calibrate_in && distance_in > 0) { // If closer than wall/calibrated object (person is present) && throw out zero readings
if (prev_inblocked == false) {
count++; // Increase count by one
if(count>=MaxOccupancy){
count = MaxOccupancy;
}
// 최대 인원 수 20으로, 20명이 넘게 들어와서 21,22로 카운트 되도 20이 되게 했다.
Serial.print("Count: "); // 줄바꿈 하지 않으면 serial.print(매개인자);
Serial.println(count); // 줄바꿈 하면 serial.println(매개인자); 이다.
}
prev_inblocked = true;
} else {
prev_inblocked = false;
}
if (distance_out < calibrate_out && distance_out > 0) {
if (prev_outblocked == false) {
count--; // Decrease count by one
if(count<=0){
count = 0;
}
// 시리얼 모니터에서 인원수가 -10까지 count 되는 문제점이 발생하였기에 0으로 초기화 시키게 했다.
Serial.print("Count: ");
Serial.println(count);
}
prev_outblocked = true;
} else {
prev_outblocked = false;
}
// //If there are fewer people in the shop than the limit, light is green, else it is red
if (count < limit) {
digitalWrite(LED_WAIT, LOW);
digitalWrite(LED_ENTER, HIGH);
} else {
digitalWrite(LED_WAIT, HIGH);
digitalWrite(LED_ENTER, LOW);
}
}
이후 tone 함수를 사용하는 pitches.h를 추가하여서 학교 종이 떙떙땡을 연주하려 했으나
time_interupt에서 Newping.h이 이미 사용을 하고 있어서
tone을 사용 할 수 없었다.
1. timer timer0_pin_port가 중첩 되었을 때 발생하는 ERROR:
returned 1 exit status
timer0_pin_port
(.text+0x0) multiple definition of __vector_ 7'
2. pin 겹칠 때 발생하는 ERROR : 'Serial' does not name a type,
관련 정보를 담은 사이트이다.
https://blog.naver.com/ann_arbor/221356498570
★ ATmega328 타이머(Timer) 별 관련 함수 및 라이브러리
아두이노 우노, 나노, 르로미니 보드들은 ATmega328(128) CPU를 사용하며 각 타이머별 관련된 함수 및...
blog.naver.com
대안으로 toneAC 라이브러리를 설치했다.
이후 10번핀에 피에조 스피커를 연결 시켰다.
마지막으로 겨우 해냈다.
#include <NewPing.h>
#include <toneAC.h>
#include "pitches.h"
//Defining where the components are attached
#define TRIG_IN A1
// 입장 할 때, A1에서 트리거를 발사 할 것이다.
#define TRIG_OUT 3
// 퇴장 할 때, 3에서 트리거를 발사 할 것이다.
#define ECHO_IN A2
// 입장 할 때, A2에서 트리거를 수신 받을 것이다.
#define ECHO_OUT 4
// 퇴장 할 때, 4에서 트리거를 수신 받을 것이다.
#define LED_WAIT 12
// 이미 자리가 찼음을 의미하는 빨간색LED에는 12번 핀을 설정한다.
#define LED_ENTER 8
// 입장해도 된다고 비었음을 의미하는 초록색LED에 8번핀을 할당한다.
// toneAC 함수가 9,10번 핀으로 신호를 출력(output)하기 때문에 소리가 날 때, LED가 같이 깜빡거림
#define iterations 5 //Number of readings in the calibration stage
#define MAX_DISTANCE 150 // Maximum distance (in cm) for the sensors to try to read.
#define DEFAULT_DISTANCE 45 // Default distance (in cm) is only used if calibration fails.
// 교정 실패 했을 때를 위해서 사용한다.
#define MIN_DISTANCE 15 // Minimum distance (in cm) for calibrated threshold.
// 문지방을 무시하기 위한 최소거리를 설정한다.
float calibrate_in = 0, calibrate_out = 0; // The calibration in the setup() function will set these to appropriate values.
float distance_in, distance_out; // These are the distances (in cm) that each of the Ultrasonic sensors read.
int count = 0, limit = 5; //Occupancy limit should be set here: e.g. for maximum 8 people in the shop set 'limit = 8'.
bool prev_inblocked = false, prev_outblocked = false; //These booleans record whether the entry/exit was blocked on the previous reading of the sensor.
// 불 대수를 통해서 선언한다? (불대수 예제 공부가 필요하네)
NewPing sonar[2] = { // Sensor object array.
// 초음파 센서 두 개를 사용 할 것이기 때문에 배열의 크기를 2로 선언해준다.
NewPing(TRIG_IN, ECHO_IN, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
NewPing(TRIG_OUT, ECHO_OUT, MAX_DISTANCE)
};
int melody[] = { /* [] 대괄호로써 배열을 쓰겠다.
변수를 여러번 사용할 필요 없이 한 번만 변수를 선언하는 장점이 있다.
[배열의 크기]
int는 변수의 형태
melody는 변수의 이름
ex) meolody[3] = melody[0], melody[1], melody[2]로 이루어져 있다.
메모리 값은 0에서 부터 시작한다. */
NOTE_G4, // {주파수}
NOTE_G4, // 각 배열마다 콤마로 구분을 시켜준다.
NOTE_A5,
NOTE_A5,
NOTE_G4,
NOTE_G4,
NOTE_E4,
NOTE_G4,
NOTE_G4,
NOTE_E4,
NOTE_E4,
NOTE_D4,
0, // 쉬어간다.
NOTE_G4,
NOTE_G4,
NOTE_A5,
NOTE_A5,
NOTE_G4,
NOTE_G4,
NOTE_E4,
NOTE_G4,
NOTE_E4,
NOTE_D4,
NOTE_E4,
NOTE_C4,
0,};
int noteDurations[] = { // 음의 길이를 나타내는 배열
1,1,1,1,
1,1,2,
1,1,1,1,
3,1,
1,1,1,1,
1,1,2,
1,1,1,1,
3,1,};
/*
A quick note that the sonar.ping_cm() function returns 0 (cm) if the object is out of range / nothing is detected.
We will include a test to remove these erroneous zero readings later.
*/
void setup() {
Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
// LCD로 표현하게끔 응용해봐야겠다.
pinMode(2, OUTPUT); pinMode(5, OUTPUT); pinMode(A0, OUTPUT); pinMode(A3, OUTPUT); pinMode(11, OUTPUT);
digitalWrite(2, HIGH); digitalWrite(5, LOW); digitalWrite(A0, HIGH); digitalWrite(A3, LOW); digitalWrite(11, LOW);
pinMode(LED_WAIT, OUTPUT), pinMode(LED_ENTER, OUTPUT);
digitalWrite(LED_WAIT, HIGH); digitalWrite(LED_ENTER, HIGH); //Both LEDs are lit to alert user to ongoing calibration.
Serial.println("Calibrating...");
delay(1500);
for (int a = 0; a < iterations; a++) {
delay(50);
calibrate_in += sonar[0].ping_cm();
delay(50);
calibrate_out += sonar[1].ping_cm();
delay(200);
}
calibrate_in = 0.75 * calibrate_in / iterations; //The threshold is set at 75% of the average of these readings. This should prevent the system counting people if it is knocked.
calibrate_out = 0.75 * calibrate_out / iterations;
if (calibrate_in > MAX_DISTANCE || calibrate_in < MIN_DISTANCE) { //If the calibration gave a reading outside of sensible bounds, then the default is used
calibrate_in = DEFAULT_DISTANCE;
}
if (calibrate_out > MAX_DISTANCE || calibrate_out < MIN_DISTANCE) {
calibrate_out = DEFAULT_DISTANCE;
}
Serial.print("Entry threshold set to: ");
Serial.println(calibrate_in);
Serial.print("Exit threshold set to: ");
Serial.println(calibrate_out);
digitalWrite(LED_WAIT, LOW); digitalWrite(LED_ENTER, LOW); //Both LEDs are off to alert user that calibration has finished.
delay(1000);
}
void loop() {
distance_in = sonar[0].ping_cm();
delay(40); // Wait 40 milliseconds between pings. 29ms should be the shortest delay between pings.
distance_out = sonar[1].ping_cm();
delay(40);
if (distance_in < calibrate_in && distance_in > 0) { // If closer than wall/calibrated object (person is present) && throw out zero readings
if (prev_inblocked == false) {
count++; // Increase count by one
for(int thisNote = 0; thisNote < 26; thisNote++) {
int noteDuration = 250 * noteDurations[thisNote];
toneAC(melody[thisNote],100,noteDuration,false);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
toneAC();
}
/* 사람이 들어 올 때마다 학교종이 땡땡땡을 울리게 설정했다.
단점으로는 노래가 끝난 뒤에야 다음 코드로 넘어가기 때문에 빠르게 count를 할 수 없다.
*/
if(count>limit){
count = limit;
}
/* 최대 인원 수 5명인데 실제 코드는 21,22로 카운트로 계속 증가하는 단점이 있어서 넘어버리면
limit인 5로 설정되게 되게 했다. */
Serial.print("Count: "); // 줄바꿈 하지 않으면 serial.print(매개인자);
Serial.println(count); // 줄바꿈 하면 serial.println(매개인자); 이다.
}
prev_inblocked = true;
} else {
prev_inblocked = false;
}
if (distance_out < calibrate_out && distance_out > 0) {
if (prev_outblocked == false) {
count--; // Decrease count by one
if(count<=0){
count = 0;
}
// 시리얼 모니터에서 인원수가 -10까지 count 되는 문제점이 발생하였기에 0으로 초기화 시키게 했다.
Serial.print("Count: ");
Serial.println(count);
}
prev_outblocked = true;
} else {
prev_outblocked = false;
}
// //If there are fewer people in the shop than the limit, light is green, else it is red
if (count < limit) {
digitalWrite(LED_WAIT, LOW);
digitalWrite(LED_ENTER, HIGH);
} else {
digitalWrite(LED_WAIT, HIGH);
digitalWrite(LED_ENTER, LOW);
}
}
'아두이노' 카테고리의 다른 글
아두이노를 이용한 FFT 출력 및 스펙트럼 관찰 - 1, 2 (0) | 2021.05.03 |
---|---|
아두이노 기초 유튜브 강의 (0) | 2021.05.03 |
초음파센서 다중제어 예제 Newping 스스로 익히기 (0) | 2021.04.30 |
2. 아두이노 초음파 센서 LCD에 나타내기 실습 (1) | 2021.04.25 |
1. 아두이노 LCD로 조도센서 값 읽어오기 (0) | 2021.04.24 |
댓글