자작 정수기 컨트롤러 8, 유량센서(Flow meter) 적용
플로우센서를 적용하겠습니다. 우선 위 사진처럼 아두이노 5V, GND, D2 핀에 연결했습니다. DFRobot 사의 IO Expansion Shield를 이용하니 따로 브레드보드가 필요없어 테스트하기 참 편하네요!
그 다음, 소스코드는 Adafruit 에서 제공하는 예제를 사용했습니다. 따로 라이브러리는 필요없고 인터럽트 방식을 이용했는데, 초보인 저에게는 너무 어려운 문제라 그냥 예제를 고쳐서 쓸 수 밖에 없었습니다. 아래 링크 따라가시면 예제 나옵니다.
Flow Meter Example (https://github.com/adafruit/Adafruit-Flow-Meter)
기본 예제를 불러 온 모습입니다. 플로우센서가 연결된 디지털 핀만 확인하고 바로 실행했습니다.
// which pin to use for reading the sensor? can use any pin!
#define FLOWSENSORPIN 2
// count how many pulses!
volatile uint16_t pulses = 0;
// track the state of the pulse pin
volatile uint8_t lastflowpinstate;
// you can try to keep time of how long it is between pulses
volatile uint32_t lastflowratetimer = 0;
// and use that to calculate a flow rate
volatile float flowrate;
// Interrupt is called once a millisecond, looks for any pulses from the sensor!
SIGNAL(TIMER0_COMPA_vect) {
uint8_t x = digitalRead(FLOWSENSORPIN);
if (x == lastflowpinstate) {
lastflowratetimer++;
return; // nothing changed!
}
if (x == HIGH) {
//low to high transition!
pulses++;
}
lastflowpinstate = x;
flowrate = 1000.0;
flowrate /= lastflowratetimer; // in hertz
lastflowratetimer = 0;
}
void useInterrupt(boolean v) {
if (v) {
// Timer0 is already used for millis() - we'll just interrupt somewhere
// in the middle and call the "Compare A" function above
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
} else {
// do not call the interrupt function COMPA anymore
TIMSK0 &= ~_BV(OCIE0A);
}
}
void setup() {
Serial.begin(9600);
Serial.print("Flow sensor test!");
pinMode(FLOWSENSORPIN, INPUT);
digitalWrite(FLOWSENSORPIN, HIGH);
lastflowpinstate = digitalRead(FLOWSENSORPIN);
useInterrupt(true);
}
void loop() // run over and over again
{
float liters = pulses;
liters /= 7.5;
liters /= 60.0;
if ( liters != 0 )
{
Serial.print(liters); Serial.println(" Liters");
}
delay(100);
}
예제 전체 소스코드이고 아래는 그 실행된 화면입니다.
위 화면처럼 단순히 리터값으로 변환해서 출력해주는 기능만 합니다. 0값이 아닐 경우 출력하도록 했기에, 더이상 입력이 없어도 같은 값을 반복해서 출력합니다.
이제, 이 소스를 기존 소스에 붙여 넣고, 스위치를 하나 연결해서 출력을 제어하도록 했습니다.
사진처럼 푸시버튼을 하나 연결했습니다.
inputSwitch = digitalRead(SWITCHPIN); // 스위치 입력값을 받음
if ( inputSwitch != prevState ) // 이전 상태와 다르다면....즉, On 또는 Off로 변화가 생겼다면....
{
prevState = inputSwitch; // 우선 다음번 비교를 위해 현재 입력값 저장
if ( inputSwitch == HIGH ) // 스위치가 On 이라면.... 즉, Off -> On 으로 변화됨
{
if ( switchState == false ) // switchState 는 흐름 측정 유무를 체크하는 변수로
{ // 값이 false 라면 현재 흐름이 없는 즉, 첫번째로 스위치를 눌렀음을 의미
switchState = true; // 첫번째 눌렀으므로 흐름을 측정하도록 On!!
}
else // switchState 가 true 즉, 현재 흐름을 측정하고 있는 상태이므로, 두번째로 스위치를 눌렀음을 의미
{
switchState = false; // 두번째 스위치를 눌렀으므로 흐름 측정을 Off!!
}
}
}
추가된 소스코드입니다. 이 스위치를 한번 누르면 물 흐름을 측정하고 다시 누르면 측정을 멈춥니다. 이를 위해서, 스위치가 ON/OFFl 중 어느 상태인지, 첫번째와 두번째 중 어떤 건지 체크하도록 소스를 구성했습니다.
실행된 화면입니다. 참고로, 흐름을 그냥 센서를 입에 대고 불어서 발생시켰읍니다.^^;; 출력값을 원래 리터였는데, 1000 을 곱해서 밀리리터로 변환시켰습니니다만, 단위명을 안고쳐서 Liters로 표시되고 있네요!
그 다음, 이제 출력을 시리얼 모니터가 아닌 OLED로 출력하도록 수정했습니다. 아래는 전체 소스이고, 이어서 작동 영상을 올렸습니다. 그런데, 한가지 문제점이 있어서 생각대로 표현이 안되네요! 아래쪽에서 얘기하겠습니다.