새소식

Projects

치워줘 - 알쓰(알뜰한 쓰레기통) [2] - 아두이노로 구현

  • -

지난 포스터 때는 알쓰를 왜 만들게 되었는지와 시현영상을 보여드렸습니다

 

(안보신 분들은 먼저보세요)

 

치워줘 - 알쓰(알뜰한 쓰레기통) [1] - 프로젝트 개요

 

아래는 전체 소스코드 입니다.

 

#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>

#define ssid "iptime"
#define password "gksmf1648"

LiquidCrystal_I2C lcd(0x3F, 16, 2); //I2C 주소 0x27 or 0x3F
SoftwareSerial espSerial(4, 5);

int trig = 3, echo = 2;
int rLED = 8, oLED = 9, yLED = 10, cLED = 11, gLED = 12;
int cmdSize = 0;
long previousMillis = 0;
char a;
char b;
void setup() {

  lcd.begin(16, 2); //16열 2행짜리 LCD를 사용하겠다.
  lcd.init();
  
  Serial.begin(9600);
  espSerial.begin(9600);
  connectWifi();
  
  lcd.backlight();
  pinMode(3, OUTPUT);
  pinMode(2, INPUT);
  pinMode(8,OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  
  lcd.setCursor(0, 0);
  lcd.print("[");
  lcd.setCursor(6, 0);
  lcd.print("] --% WIFI");
}

void customclear()
{
 // ensures all custom character slots are clear before new custom
 // characters can be defined.
 byte blank[8] =
 {
   0b00000, 
   0b00000, 
   0b00000, 
   0b00000, 
   0b00000, 
   0b00000, 
   0b00000, 
   0b00000,};
 for(int i = 0; i < 8; i++)
 {
   lcd.createChar(i, blank);
 }
}

void customset1()
{
  customclear();
  
  byte nemo[8] = { 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111,};     //0 네모
  byte heart[8] = {0b00000, 0b01010, 0b10101, 0b10001, 0b10001, 0b01010, 0b00100, 0b00000,};     //1 하트
  byte Achi[8] = {0b00001, 0b01001, 0b11101, 0b01001, 0b01001, 0b10101, 0b00001, 0b00001,};      //2 치 
  byte Awo[8] = {0b01001, 0b10101, 0b01001, 0b11111,0b01001, 0b01011, 0b01001, 0b00000,};        //3 워
  byte Ajo[8] = {0b11111, 0b00100, 0b01010, 0b10001, 0b00100, 0b00100, 0b11111, 0b00000,};       //4 조
  byte Aal[8] = {0b01010, 0b10110, 0b01011, 0b00010, 0b01110, 0b00100, 0b01000, 0b01100,};       //5 알 
  byte Ath[8] = {0b00000, 0b01010, 0b01010, 0b10101, 0b10101, 0b00000, 0b11111, 0b00000,};       //6 쓰 
  byte eightno[8] = {0b00100, 0b00110, 0b00101, 0b00101, 0b00100, 0b01100, 0b11100, 0b01000,};   //7 8분음표
  
  lcd.createChar(0, nemo);
  lcd.createChar(1, heart);
  lcd.createChar(2, Achi);
  lcd.createChar(3, Awo);
  lcd.createChar(4, Ajo);
  lcd.createChar(5, Aal);
  lcd.createChar(6, Ath);
  lcd.createChar(7, eightno); 
}

void loop() {

  float fDist = distance(); // 거리측정
  int fDistp = (1-fDist/37)*100;
  customset1();
  a = fDistp;
  b = fDistp;
  long currentMillis = millis();

  if (currentMillis - previousMillis >= 7000) {

    previousMillis = currentMillis;
    if(fDistp>0){requestBusInfo();}
  }

  if (espSerial.available()) {

    Serial.write(espSerial.read());
  }
  

  
  if(fDist <= 8){
   lcd.clear();
   lcd.print("["); lcd.write(0); lcd.write(0); lcd.write(0); lcd.write(0); lcd.write(0); lcd.print("]"); if(fDistp > 0){lcd.print(fDistp);} lcd.print("% WIFI");
   lcd.setCursor(0,1);
   lcd.write(1); lcd.write(2); lcd.write(3); lcd.write(4); lcd.print("'s "); lcd.write(5); lcd.write(6); lcd.write(7); lcd.print(" ");   // (하트) 치워조's (알)(쓰)음표 (하트) 
   digitalWrite(8, HIGH); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(11, LOW); digitalWrite(12, LOW);
   
  }else if(fDist <= 15){
    lcd.clear();
    lcd.print("["); lcd.write(0); lcd.write(0); lcd.write(0); lcd.write(0); lcd.print(" ]"); if(fDistp > 0){lcd.print(fDistp);} lcd.print("% WIFI");
    lcd.setCursor(0,1);
    lcd.write(1); lcd.write(2); lcd.write(3); lcd.write(4); lcd.print("'s "); lcd.write(5); lcd.write(6); lcd.write(7); lcd.print(" ");   // (하트) 치워조's (알)(쓰)음표 (하트) 
   digitalWrite(8, LOW); digitalWrite(9, HIGH); digitalWrite(10, LOW); digitalWrite(11, LOW); digitalWrite(12, LOW);
  
  }else if(fDist <= 22){
    lcd.clear();
    lcd.print("["); lcd.write(0); lcd.write(0); lcd.write(0); lcd.print("  ]"); if(fDistp > 0){lcd.print(fDistp);} lcd.print("% WIFI");
    lcd.setCursor(0,1);
    lcd.write(1); lcd.write(2); lcd.write(3); lcd.write(4); lcd.print("'s "); lcd.write(5); lcd.write(6); lcd.write(7); lcd.print(" ");  // (하트) 치워조's (알)(쓰)음표 (하트) 
   digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, HIGH); digitalWrite(11, LOW); digitalWrite(12, LOW);
    
  }else if(fDist <= 29){
    lcd.clear();
    lcd.print("["); lcd.write(0); lcd.write(0); lcd.print("   ]"); if(fDistp > 0){lcd.print(fDistp);} lcd.print("% WIFI");
    lcd.setCursor(0,1);
    lcd.write(1); lcd.write(2); lcd.write(3); lcd.write(4); lcd.print("'s "); lcd.write(5); lcd.write(6); lcd.write(7); lcd.print(" ");   // (하트) 치워조's (알)(쓰)음표 (하트) 
    digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(11, HIGH); digitalWrite(12, LOW);

  }else if(fDist <= 36){
    lcd.clear();
    lcd.print("["); lcd.write(0); lcd.print("    ]"); if(fDistp > 0){lcd.print(fDistp);} lcd.print("% WIFI");    lcd.setCursor(0,1);
    lcd.write(1); lcd.write(2); lcd.write(3); lcd.write(4); lcd.print("'s "); lcd.write(5); lcd.write(6); lcd.write(7); lcd.print(" ");   // (하트) 치워조's (알)(쓰)음표 (하트) 
    digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(11, LOW); digitalWrite(12, HIGH);
   
  }else{
    lcd.clear();
    lcd.print("[     ");
    lcd.print("] --% WIFI");
    lcd.setCursor(0,1);
    lcd.write(1); lcd.write(2); lcd.write(3); lcd.write(4); lcd.print("'s "); lcd.write(5); lcd.write(6); lcd.write(7); lcd.print(" ");   // (하트) 치워조's (알)(쓰)음표 (하트) 
    digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(11, LOW); digitalWrite(12, LOW);
  }
}

float distance() // 거리 20번 측정해서 평균을 돌려주는 함수
{  
  float fDuration, fDistance=0;
  for(int i=0; i<20; i++)
  {
    digitalWrite(trig, HIGH); 
    delay(10); 
    digitalWrite(trig, LOW);
    fDuration = pulseIn(echo, HIGH);
    fDistance += 17 * fDuration / 1000.0;
    delay(120);
  }
  return (fDistance/20.0);  // 거리 평균값 리턴
}

void connectWifi() {

  espSerial.println("AT+CWMODE=1");
  while (espSerial.available()) {
    Serial.write(espSerial.read());
  }
  delay(350);

  espSerial.println("AT+CIPMUX=0");
  while (espSerial.available()) {
    Serial.write(espSerial.read());
  }
  delay(350);

  espSerial.print("AT+CWJAP=\"");
  espSerial.print(ssid);
  espSerial.print("\",\"");
  espSerial.print(password);
  espSerial.println("\"");
  while (espSerial.available()) {
    Serial.write(espSerial.read());
  }
}

void requestBusInfo() {
  cmdSize = strlen("GET /set?amount=10,20 HTTP/1.1")
            + strlen("Host: http://220.68.27.153:3000/set?amount=10,20 \r\nConnection: close\r\n\r\n") + 2;
  espSerial.println("AT+CIPSTART=\"TCP\",\"220.68.27.153\",3000");
  delay(200);
  espSerial.print("AT+CIPSEND=");
  delay(100);
  espSerial.println(cmdSize);
  delay(100);
  espSerial.print("GET /set?amount=");
  espSerial.print(a+0); espSerial.print(","); espSerial.print(b+0); espSerial.println(" HTTP/1.1");
  espSerial.println("Host: http://220.68.27.153:3000/set?amount=10,20 \r\nConnection: close\\r\n\r\n");
}



 

길지는 않지만 대부분의 코드는 LCD를 표현하기 위한 코드입니다. 핵심코드는 양이 그리 많지 않습니다.

 

기본적인 로직은 일정시간마다 (1) 초음파 센서로 쓰레기까지의 거리를 측정하고 (2) 측정한 거리를 서버로 보냅니다.

 

사실 이게 전부입니다. 일정시간마다 매번 체크를 해야하기 때문에 일단 (1)과 (2)로직은 loop()에 있어야 합니다. 

 

void loop() {

  float fDist = distance(); // 거리측정
  int fDistp = (1-fDist/37)*100;
  customset1();
  a = fDistp;
  b = fDistp;
  long currentMillis = millis();

  if (currentMillis - previousMillis >= 7000) {

    previousMillis = currentMillis;
    if(fDistp>0){sendData();}
  }

  if (espSerial.available()) {

    Serial.write(espSerial.read());
  }
  
  // 아래는 LCD 표시 부분
  
}

 

위의 코드는 loop()함수로 아두이노 실행시 계속 작동되는 로직입니다. 맨 처음은 쓰레기통 위쪽에서부터 아래까지의 거리를 리턴하는 distance()함수로 현재 쓰레기가 차 있는 정도를 파악합니다. 구체적인 방법으로는

 

(1) fDist에는 실제적인 거리값을 받아온 다음, 이 거리값이 실제 쓰레기통의 몇 %를 차지하는지 계산하여 fDistp에 저장합니다.

 

(2)다음은 millis() 함수 (아마 아두이노 내장함수 일 겁니다) 로 약 7초에 한번 씩 요청을 보내도록 설정을 해 줍니다. 

 

서버에 요청하는 함수는 sendData() 로 현재의 fDistp ( 현재 쓰레기가 몇 % 차지하고있는지) 데이터를 Server에 전송합니다. 이 과정을 계속 반복하면 정상적으로 잘 작동이 됩니다.

 

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.