산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

아두이노로 만드는 클래식 양방향 페이저 - DIY 레트로 호출기

부품 및 소모품

부품수량
Hologram 글로벌 IoT SIM 카드1
아두이노 우노 (Arduino UNO)1
아두이노 GSM 실드 V21
Adafruit LCD 실드 키트 (16x2 문자 디스플레이, I2C 2핀만 사용)1
Hammond 프로젝트 박스 4.7 x 2.6 x 1.4 투명 블루1

앱 및 온라인 서비스

프로젝트 소개

소개

90년대 후반과 2000년대 초반의 향수를 되살려 제이지는 사용하던 양방향 페이저를 직접 만들어 보았습니다. 그런데 이 아이디어가 처음 생각보다 더 유용하다는 것을 알게 되었습니다. 아이들에게 진짜 휴대폰 대신 주거나, 야외에서 혼자 일하는 사람이나 운동하는 사람을 위한 'SOS' 버튼으로 활용할 수 있습니다(크기가 더 작다면). 최근 몇 주간 이 장치는 거실에서 항상 켜져 있어 아내와 서로 재미있는 메시지를 주고받는 용도로 쓰이고 있습니다.

요약: 아두이노에 셀룰러 모뎀을 장착하고 LCD 디스플레이와 간단한 조작 버튼을 작은 인클로저에 넣어 SMS 문자 메시지를 송수신하는 장치입니다.

참고: 이 프로젝트 코드에는 LCD 실드 없이도 시리얼 인터페이스로 시스템을 실행할 수 있는 기능이 포함되어 있습니다.

하드웨어 선택

아두이노 GSM 실드와 Hologram SIM 카드를 사용하기로 했고, 아두이노 우노와 조합하는 것이 자연스러웠습니다. Adafruit의 LCD 실드는 버튼이 내장되어 있고 I2C 버스를 사용해 아두이노 핀 2개만 차지하므로(디스플레이 + 5개 버튼), 향후 확장에 유리합니다.

LCD의 파란색 백라이트와 투명 블루 인클로저가 잘 어울립니다. 세 보드를 쌓아 올리면 연결이 매우 깔끔하고, 두 실드가 서로 다른 핀을 사용하므로 전기적으로도 문제가 없습니다.

나머지 핀들은 모두 자유로워 추가 장치 연결이 가능합니다. I2C 버스에도 다른 장치를 추가할 수 있습니다.

개발 중에는 노트북 USB 전원만으로 SMS 송수신이 잘 작동했으나, GPRS 데이터 통신에는 더 많은 전력이 필요할 것으로 보입니다.

셀룰러 통신

Hologram은 SIM 카드를 사용하는 모든 기기에 셀룰러 데이터 서비스를 제공합니다. SIM 카드 등록 후 클릭 한 번으로 원하는 지역 번호의 전화번호를 부여받을 수 있습니다. 서비스를 유지하는 비용이 월 $0.40로 저렴하고, 사용하지 않을 때는 언제든 일시 정지할 수 있어 아이들용 통신기로도 좋습니다. 일반적인 요금제처럼 수신은 무료, 발신은 건당 $0.19입니다. 향후 Hologram 클라우드 서비스를 통해 데이터 연결로 메시지를 라우팅하면 비용을 더 낮출 수 있습니다. 1MB에 $0.60이면 아주 많은 텍스트 메시지를 보낼 수 있습니다.

어떤 이유인지 GSM 실드가 정상 작동함에도 GSMScanner와 GSMModem getIMEI() 함수가 제대로 작동하지 않았습니다. SMS와 GPRS 데이터 기능은 정상인데, 모뎀이 자신의 IMEI 번호를 알려주지 않는 이유를 아시는 분은 알려주시면 감사하겠습니다.

코드 및 인터페이스

Adafruit의 LCD 실드 가이드와 아두이노의 GSM 실드 시작 가이드를 바탕으로 코드를 작성했고, 나만의 사용자 인터페이스를 추가했습니다.

키보드로 명령어를 입력하는 방식이 아닌 사용자 인터페이스를 처음 프로그래밍해봐서 단순하게 만들었습니다. 위/아래 키로 보낼 메시지를 스크롤하여 선택하는 방식인데, 생각보다 쉽게 구현되었습니다.

세 보드를 작동하는 SIM 카드(본인 폰의 SIM도 가능)와 함께 쌓고 아래 코드를 업로드하면 다음과 같이 작동하는 문자 메시지 장치가 됩니다:

수신 메시지는 현재 메뉴와 상관없이 자동으로 표시되며, 백라이트가 꺼져 있었다면 켜집니다.

다음 단계로는 수신자 번호 선택 메뉴 추가, 마지막 수신자에게 자동 회신(remoteNumber() 함수 활용), 디스플레이 자동 소등으로 배터리 절약, 알림용 조명/부저/진동 모터 추가 등이 가능합니다.

최종 조립

프로젝트 박스 가공에는 드릴(일반 구멍)과 드레멀 멀티 컷팅 비트(#561, 가이드 #565)를 사용했습니다. 지그를 만들어 드레멀을 가이드했다면 더 깔끔했겠지만, 수작업으로도 만족스럽습니다.

실제 배선은 9V 배터리와 스위치 연결용 전원선뿐입니다. 배터리 없이 USB나 어댑터로 전원 공급도 가능합니다.

9V 배터리와 클립은 아두이노 옆, GSM 실드 아래(아두이노 메가 크기 정도)에 잘 들어갑니다. 헤더 핀에 전선을 납땜해 전원 연결을 쉽게 했습니다.

GSM 실드 핀 리드가 길고 구부러져 있어 아두이노 소켓을 피하게 살짝 휘어 연결했습니다. 이 때문인지 핀이 그렇게 설계된 것 같습니다. LCD 실드 핀은 짧고 앞면에 암소켓이 없어 이 설정에서는 핀을 휘는 방법 외에 다른 연결 방법이 없었습니다.

아두이노 하단의 USB 포트 납땜 리드 등을 잘라내고 양면 폼 테이프로 케이스 바닥에 고정했습니다. 보드들을 쌓아 올리면 LCD와 버튼이 케이스 상단 바로 위로 살짝 튀어나와 완벽한 마무리가 됩니다.

결론

이 시스템을 계속 개선해 나갈 예정이며, 4살 조카에게도 맡겨볼 생각입니다. 메신저로서도 잘 작동하지만, 집 안의 작은 게시판처럼 메시지를 표시하는 용도로 더 마음에 듭니다. 미적인 면도 만족스럽습니다.

향후 개선 사항: 수신자 선택 메뉴 추가, 디스플레이 자동 소등, 알림용 조명/부저/진동 모터, IFTTT 같은 서비스 연동(택배 도착 알림, 트윗 표시 등) 등 원하는 UI 동작을 자유롭게 구현할 수 있습니다.

즐거운 제작 되세요!

- Mike

내 블로그에서 더 많은 프로젝트를 볼 수 있습니다.

(이 프로젝트는 Hologram의 Hacker-In-Residence 프로그램의 일환으로 제작되었습니다. 문의: Sheena, sheena@hologram.io)

코드

아두이노용 시스템 코드 (Arduino)

/** 
 * 아두이노와 Hologram 셀룰러 서비스를 이용한 양방향 페이저 시스템
 * Mike Schaus
 * Dec 28, 2016
 * Hologram Hacker-In-Residence 프로그램의 일환으로 제작
 * 
 * 이 프로젝트는 아두이노에 셀룰러 모뎀을 장착하고 LCD 디스플레이와 
 * 간단한 조작 버튼을 작은 인클로저에 넣어 SMS 문자 메시지를 송수신합니다.
 * 
 * LCD 실드 또는 시리얼 모니터로 동작하도록 코드가 작성되어 있어
 * LCD 실드 없이도 이 코드를 사용할 수 있습니다.
 */
#include <GSM.h>
#define PINNUMBER ""
#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>

// 실드는 I2C SCL, SDA 핀 사용. 클래식 아두이노에서 아날로그 4, 5번 핀.
// 다른 I2C 센서도 버스 공유 가능.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

#define OFF 0x0
#define ON 0x1

// LCD용 화살표 특수 문자
const byte arrow[8] = {
  B00000, B00000, B01000, B01100,
  B01110, B01100, B01000, B00000
};

GSM gsmAccess(false); // 디버그 활성화하려면 true
GSM_SMS sms;

char remoteNumber[20] = "12125551212"; // 접근 가능한 번호로 변경
char senderNumber[20];
char* responses[] = {"Mike=Awesome!", "Yes", "No", "Howdy!"};
#define NUMRESPONSES (sizeof(responses)/sizeof(char *))
int position = -1;
int inByte = 0;
boolean backlight = true;
unsigned long previousMillis = 0;
#define CHECKINTERVAL 1500

void setup() {
  Serial.begin(9600);
  Serial.println(F("SMS Message Sender -- starting up..."));
  lcd.begin(16, 2);
  lcd.print(F("Hello, Hologram!"));
  lcd.setCursor(0, 1);
  lcd.print(F("Starting up..."));
  lcd.setBacklight(ON);
  lcd.createChar(0, arrow);

  boolean notConnected = true;
  while (notConnected) {
    if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
      notConnected = false;
      Serial.println(F("GSM is connected because you are so awesome"));
      Serial.println(F("Waiting for messages, or send with \"s\""));
      Serial.println();
      lcd.clear();
      lcd.setCursor(0, 0);
      homeScreen();
    } else {
      Serial.println(F("Not connected"));
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(F("Not connected"));
      delay(1000);
    }
  }
}

void showResponses() {
  lcd.clear();
  lcd.setCursor(0, 0);
  if (position < 0) position = 0;
  if (position > NUMRESPONSES - 1) position = NUMRESPONSES - 1;
  lcd.write(0);
  lcd.print(position + 1);
  lcd.print("-");
  lcd.print(responses[position]);
  if (position < NUMRESPONSES - 1) {
    lcd.setCursor(0, 1);
    lcd.print(" ");
    lcd.print(position + 2);
    lcd.print("-");
    lcd.print(responses[position + 1]);
  }
}

void homeScreen() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SMS Messenger!");
  lcd.setCursor(0, 1);
  lcd.print("Ready; up/dn snd");
  position = -1;
}

void receiveSMS() {
  char c;
  if (sms.available()) {
    Serial.println("Message received from:");
    sms.remoteNumber(senderNumber, 20);
    Serial.println(senderNumber);
    lcd.clear();
    lcd.setCursor(0, 0);
    backlight = true;
    lcd.setBacklight(ON);
    if (sms.peek() == '#') {
      Serial.println("Discarded SMS");
      sms.flush();
    }
    int i = 0;
    while (c = sms.read()) {
      i++;
      Serial.print(c);
      if (i == 17) lcd.setCursor(0, 1);
      if (i < 33) lcd.print(c);
    }
    Serial.println("\nEND OF MESSAGE");
    sms.flush();
    Serial.println("MESSAGE DELETED");
    Serial.println();
    boolean acknowledged = false;
    while (!acknowledged) {
      uint8_t buttons = lcd.readButtons();
      if (buttons & BUTTON_RIGHT) acknowledged = true;
      delay(50);
    }
    homeScreen();
    delay(400);
  }
}

void printResponseOptions() {
  for (int i = 0; i < NUMRESPONSES; i++) {
    Serial.print(i);
    Serial.print("-");
    Serial.println(responses[i]);
  }
  Serial.println();
}

void sendSMS(const char* txtMsg) {
  Serial.print("Message to mobile number: ");
  Serial.println(remoteNumber);
  Serial.println("SENDING");
  Serial.println("Message:");
  Serial.println(txtMsg);
  sms.beginSMS(remoteNumber);
  sms.print(txtMsg);
  sms.print(" --Be sure to connect with me on my blog https://mschausprojects.blogspot.com");
  if (sms.endSMS() == 1) {
    Serial.println("\nCOMPLETE!\n");
    homeScreen();
  } else {
    Serial.println("\nERROR\n");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("error");
  }
  Serial.println();
}

void loop() {
  uint8_t buttons = lcd.readButtons();
  if (buttons) {
    if (buttons & BUTTON_UP) {
      position--;
      showResponses();
      backlight = true;
      lcd.setBacklight(ON);
    }
    if (buttons & BUTTON_DOWN) {
      position++;
      showResponses();
      backlight = true;
      lcd.setBacklight(ON);
    }
    if (buttons & BUTTON_LEFT) {
      homeScreen();
      backlight = true;
      lcd.setBacklight(ON);
    }
    if (buttons & BUTTON_RIGHT) {
      backlight = !backlight;
      if (backlight) lcd.setBacklight(ON);
      else lcd.setBacklight(OFF);
      homeScreen();
    }
    if (buttons & BUTTON_SELECT) {
      if (position < 0) position = 0;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Sending...");
      lcd.setCursor(0, 1);
      lcd.print(responses[position]);
      backlight = true;
      lcd.setBacklight(ON);
      sendSMS(responses[position]);
    }
    delay(200);
  }

  if (Serial.available() > 0) {
    inByte = Serial.read();
    if (inByte == 's') {
      printResponseOptions();
      while (Serial.available() > 0) {
        char junk = Serial.read();
      }
      while (Serial.available() == 0);
      inByte = Serial.parseInt();
      sendSMS(responses[inByte]);
    }
  }

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= CHECKINTERVAL) {
    previousMillis = currentMillis;
    receiveSMS();
  }
}

회로도

실제 조립은 회로도보다 훨씬 단순합니다. 두 실드를 아두이노 위에 쌓기만 하면 대부분의 연결이 끝납니다. 배터리 전원용 배선만 추가하면 됩니다.

제조공정

  1. K30 CO2 센서: 실시간 실내 공기질 모니터링
  2. 1Sheeld와 아두이노로 시각/청각 장애인 간 소통 돕기
  3. 스마트 저금통 만들기: 아두이노 나노로 동전 인식기 제어하기
  4. 아두이노 블루투스로 LED 제어하기 - HC-05 & MIT App Inventor 입문 가이드
  5. DFRobot 정전식 지문 인식 센서 아두이노/ESP8266 연동 가이드
  6. 아두이노 메가와 센서를 활용한 인터랙티브 넥시온 HMI 프로젝트
  7. 아두이노 메가 기반 닌텐도 눙크 컨트롤 6자유도 로봇 암 키트
  8. 아두이노 우노와 이더넷 실드로 정확한 태양광 복사량 측정하기
  9. 컴팩트 아두이노 레이더 시스템: HC-SR04 초음파 센서 & 1.8인치 디스플레이
  10. 아두이노로 음악 톤 만들기: 88키 피아노 음계 구현 가이드