알리에서 한 달도 안되서 온 35달러짜리 무선 탱크!!

무려 카메라가 달려 있어서 실시간 동영상 감시가 가능하다 @.@

30만 화소이기 때문에 화질을 크게 기대할 수 없지만 획기적이다!!


아두이노 강의 할 때 어린 학생들이 RC-Car 조립하는데 너무 많은 에너지를 소모하고, 결과물 품질도 일정하지 않아서, 기성 제품을 이용하여 커리큘럼을 작성하려고, 몇 가지 종류를 구매하여 테스트 하기로 했는데, 제일 처음 도착!!


전체적인 품질은 가격 대비 만족!

  • 카메라 전송에 트래픽을 많이 사용해서인지, 반응이 느려짐.  (패킷 자체가 늦게 도달하는 것으로 보임)


오픈 소스도 있음 @.@

일일히 패킷 캡쳐해서 강의 자료 만들까 했는데 다행이다 ^^;;


동작 확인은 유튜브에서 검색하면 많이 나옵니다.


원격 집안 감시용으로 개조 할 수 있을 지 고민 중입니다.





구매 링크는 아래를 참고하시기 바랍니다.




'etc > 제품 리뷰' 카테고리의 다른 글

투명펜 (자외선 잉크)  (0) 2017.05.08
중국산 저가 USB 카메라  (0) 2017.03.10
중국산 저가 무선 자동차  (0) 2017.03.06
i-Spy 중국산 저가 원격 조종 탱크  (0) 2017.03.02

Posted by 류종택


  • 주제: IoT
  • 내용
    • 1일차: 아두이노 교육
    • 2일차: 아이디발표 및 개발
오랫만에 대학생을 대상으로 교육을 진행했습니다.  하루 교육 받고 하루만에 정말 반짝이는 아이디어와 멋진 작품들을 만들어 주었습니다.





꺄하하 ^^*



Posted by 류종택

[사진 1]



raspberry pi zero가 구하기도 힘들고, orange pi zero가 새로 나왔다고 해서 구매를 했는데 이제서야 왔네요.


일단 제가 생각한 orange pi zero의 장점은

  • 구하기 쉽다.  (강의해야 하는데 raspberry pi zero는 항상 재고가 없다)
  • wifi 내장으로 좀 더 쉽게 인터넷을 사용 할 수 있다.


그러나, 단점으로는

  • raspberry pi zero에 비해 자료가 부족하다.
  • 설치 과정에도 문제가 발생
    • 공식 자료 다운로드 링크가 깨짐 (2016년 12월 1일 현재)
    • 바이두 링크는 살아 있지만, 느리고 회원 가입해서 프로그램 설치해야 함
    • Armbian for orange pi zero를 사용했지만, 설치 후 wifi 접속 과정에 문제가 있어 많은 시간을 허비함
      • 구글에서 검색 된 자료에는 이전 버전에 대한 내용으로 이제는 그런 과정이 필요없으며, 제대로 되지도 않습니다.
      • nmcli dev wifi connect <ssid> password <password>
    • 발열이 심하다고 합니다.  그래서 조그마한 발열판을 붙였습니다.




설치 과정 - SD 카드 준비

  • SDFormatter 를 설치하고 TF 카드를 포멧합니다.
  • 옵션에서 Format Size Adjustment를 ON으로 변경하고 포멧을 합니다.

[그림 1]

[그림 2]





설치과정 - 부팅 및 기초 설정

[그림 3]

  • 터미널을 접속하면 아이디와 암호를 묻습니다.

    • 아이디: root

    • 암호: 1234

  • 로그인이 완료되면 바로 암호를 변경하도록 합니다.  기존 암호를 넣고 새로운 암호를 두 번 입력합니다.

  • 이어서 사용자 등록을 진행합니다.  아이디와 암호를 넣고 나머지 정보를 대충 입력합니다.

  • apt-get upgrade를 해서 최신 상태로 업데이트 합니다.

    • 저의 경우에는 에러가 납니다.

    • 다른 것을 처리하다가 다시 시도해서 성공했습니다.

[그림 4]

  • GPIO를 다루기 위해서 라이브러리를 설치합니다.

  • # git clone https://github.com/zhaolei/WiringOP 을 실행합니다.

  • 이후 [그림 5]와 같이 설치를 합니다.

[그림 5]



[그림 6]

  • WiringOP 설치가 완료되면 [그림 6]과 같이 표시 됩니다.


[그림 7]

  • [그림 7]과 [그림 8]과 같이 테스트 프로그램을 작성해봅니다.


[그림 8]



[그림 9]

  • [그림 9]처럼 컴파일이 완료되면, ./blink를 실행합니다.
    • [사진 1]과 [사진 2]처럼 LED가 깜박이게 됩니다.

[사진 2]





혹시나 WiringOP 저장소가 또 사라질 지 몰라서 현재 버전을 파일로 올려둡니다.

WiringOP-h3.zip



Posted by 류종택

주요기능

  • 웹 문서 공유

  • 1:1 채팅

  • 채팅룸 개설 및 초대






Posted by 류종택




Posted by 류종택






주체: IT조선

내용: 아두이노 어린이 코딩 교육 (4주 4일, 1일 3시간)


기사: http://it.chosun.com/news/article.html?no=2824333&sec_no=1


교육 문의 및 신청



Posted by 류종택

PHP에서 json_encode($DB) 형태로 리턴 받은 문자열이 아래와 같은 형식을 취합니다.


[ {JSON #1}, {JSON #2} ... ]

이넘을 분리해서 각각의 JSON 문자열을 TStringList에 하나씩 Add 시켜 줍니다.


소스: https://github.com/ryujt/ryulib4delphi/blob/master/XE7/JsonUtils.pas 


사용법은 간단하니까 생략 ㅡ.ㅡ;;


Posted by 류종택



자주 쓰는 형태인데, 매번 스래드 안에서 PostMessage를 날려서 사용하다보니 불편해서 유닛으로 만들었습니다.


사용법은 아래와 같습니다.

procedure TfmMain.FormCreate(Sender: TObject);
begin
  AsyncTask(
    // This will execute task asynchronously by new thread without blocking.
    procedure (AUserData:pointer)
    begin
      Sleep(1000 * 3);
    end,

    // This will execute by main thread after above code completed.
    procedure (AUserData:pointer) 
    begin
      fmMain.Caption := 'Done';
    end
  );
end;

AsyncTask() 함수는 두 개의 익명함수가 필요합니다.  첫 번 째 함수는 별도의 스레드에 의해서 비동기적으로 실행됩니다.  그리고, 실행이 끝나고 난 뒤에는 두 번 째 익명함수가 실행됩니다.  두 번 째 익명함수는 메인 스래드에서 실행되기 때문에 UI 접근을 해도 문제가 되지 않습니다.


AUserData는 AsyncTask(익명함수, 익명함수, UserData) 와 같이 마지막 인자로 넘겨준 포인터 값입니다.  생략하면 nil이 됩니다.


소스는 아래의 링크를 참고하시기 바랍니다.







Posted by 류종택




오픈소스를 이용한 값싼 미아방지 장치


류도영




제작동기


이 제품을 만들게 된 이유는 동생이 낯선 사람을 잘 따르기 때문에 걱정되었기 때문이다.  더구나 예전에 이모가 기르던 고양이가 한눈 판 사이에 도망갔던 경험도 있다.



기존 제품의 문제점


부모님과 아이디어를 나누는 도중에 유사한 제품이 있다는 걸 알았다. 하지만 잘 사용되지 않는 것을 알게 되어 사람들에게 그 이유를 물어보았다. 그 결과는 다음과 같다.

  • 제품이 있는 줄 몰랐다: 3명

  • 비싸다: 8명

  • 필요 없을 것 같다: 4명

그래서 나는 누구나 쉽게 사용할 수 있는 값싼 미아 방지 제품을 만들고 싶었다. 게다가 평상시에 관심을 갖고 있던 아두이노를 응용하면 실용적인 제품을 만들 수 있다고 생각했다.



주요 부품 구성


이 제품을 만들기 위한 부품은 다음과 같다.  대량으로 만들면 더욱 가격이 싸진다.

  • 무선 송수신 모듈: 700원

  • 부저: 100원

  • 아두이노 칩: 820원 (2개 필요)

  • 기타

    • 건전지

    • 제품 박스



작품 요약 및 원리

아이에게 송신기를 부착하고 부모는 수신기를 지니고 다닌다. 아이가 일정 거리 이상 멀어지면, 신호가 약해지는 것을 감지해 알람을 울린다.  송신기에서는 일정 주파수의 전파를 발생한다. 전파는 멀어질수록 약해지므로 수신기에 신되는 전파가 일정 시간 내에 들어오지 않으면 알람을 울린다.



기대효과


값싸기 때문에 많은 사람들이 쉽게 사용할 수 있고, 사람이 많은 곳으로 나들이 갔을 때  안심할 수 있다. 애완견이나 자전거에도 활용 할 수 있다.



기타 아이디어


  • 수신기 쪽에는 알람과 함께 진동으로 알려준다.

  • 거리 제한을 사용자가 직접 제한할 수 있게 만든다.

  • 아이쪽에서도 알람이 울리도록 한다.

  • 미아 찾기 앱을 이용해 오픈 된 인터넷을 만나면 부모에게 위치를 알려준다.

  • 공공기관 등에서 미아 방지용으로 공유기를 오픈하는 것도 괜찮을 것 같다.




제작 과정 - 무선 모듈 테스트


[사진 1] 송신 모듈에서 데이터를 보내지 않을 때


[사진 2] 송신 모듈에서 데이터를 보낼 때


송신기와 수신기의 동작 원리를 알아보기 위해서 다음과 같이 실험을 했다.

  • 송신기를 부착한다

  • 송신기의 VCC는 빨간색 (+) 줄 아무 곳이나 끼운다.

  • 송신기의 GND는 파란색 (-) 줄 아무 곳이나 끼운다.

  • 수신기를 부착한다.

  • 수신기의 VCC는 빨간색 (+) 줄 아무 곳이나 끼운다.

  • 수신기의 GND는 파란색(-) 줄 아무 곳이나 끼운다.

  • 수신기의 DATA는 LED의 (+) 에 연결하다.

  • LED의 (-)는 파란색 줄 아무 곳에나 끼운다.

  • 이 상태에서 [사진 1]과 같이 LED에 불이 들어오는 지 확인한다.

  • 송신기의 DATA를 빨간색(+) 줄에 끼우면 신호가 전송된다.

  • 이때 수신기에 연결되어 있는 LED의 불이 밝아졌다가 꺼진다.  즉, 수신기가 신호를 받지 않을 때는 LED가 켜져 있고, 신호를 받고 있을 때는 LED가 꺼진다.



제작 과정 - 아두이노 연결


[사진 3] 수신기

  • 부저:  j9 (+) - j12

  • RF 433 MHz수신기

    • j20 - (-)

    • j21

    • j22

    • j23 - (+)

  • LED: a21 - (-)

  • 점퍼선

    • f21 - c21

    • b21 - a4


[사진 4] 송신기

  • 송신기

    • j20 - j11

    • j21 - (+)

    • j22 - (-)



[사진 5] 작게 만든 송신기


[사진 5]는 [사진 4]의 송신기를 작게 만든 것이다.  실제 사용은 팔찌 모양으로 만들고 싶다.




프로그램 설명 - 송신기


// 아두이노가 켜지면 한 번 실행 된다.

// 프로그램에 필요한 준비 작업을 하는 공간

void setup() {

 // 아두이노의 2번 핀을 출력 모드로 바꾼다.

 // 이제부터 아두이노 2번 핀에서는 전기를 내보 낼 수가 있다.

 pinMode(2, OUTPUT);

}


void loop() {

 // 2번 핀에 전기를 내보낸다.

 digitalWrite(2, HIGH);


 // 0.1초 동안 기다린다.

 delay(100);


 // 2번 핀의 전기를 끈다.

 digitalWrite(2, LOW);


 // 0.1초 동안 기다린다.

 delay(100);

}


이렇게하면 송신기에서 계속 신호가 나가게 된다.  나중에는 글자로 된 신호를 보내서 어떤 송신기가 신호를 보내는 지 확인 할 수 있도록 개선하려고 한다.




프로그램 설명 - 수신기


unsigned long old_tick;

unsigned long tick;


void setup() {

 // millis()는 아두이노가 켜진 이후 흐른 시간을 알려준다.

 // 현재까지의 시간을 old_tick에 넣어준다.

 old_tick = millis();

}


void loop() {

 // analogRead(0)은 아날로그 방식으로 0번 핀에서 전기를 읽어 온다.

 // 즉, 0번 핀으로 얼마나 큰 전기가 흘러 들어 오는 지 알 수 있다.

 // 0번 핀에 들어 오는 전기가 300보다 크다면, 현재까지의 시간을 old_tick에 넣어준다.

 if (analogRead(0) > 300) old_tick = millis();  


 // 현재까지의 시간을 tick에 넣어준다.

 tick = millis();


 // 1초 동안 신호가 없으면 4번 핀에 연결 된 부저로 100Hz의 알람을 울린다.

 if ((tick - old_tick) > 1000) {

   tone(4, 100);

 } else {

   noTone(4);

 }

}


부저가 울리면서 발생하는 잡음 때문에 알람이 울렸다가 끊어졌다가 반복된다.  이 부분은 사용에 문제가 없기 때문에 걱정하지 않아도 된다.



Posted by 류종택

인터넷 시간을 통해서 주기적으로 실제 시간을 업데이트해주는 시계입니다.  시간을 맞출 필요가 없이 스스로 알아서 해결합니다 ^^*


동작 사진


옆면


테스트 과정




3D 모델링 파일


부품 설치


우선 NodeMCU 보드를 400 tie 빵판 맨 위에 끼어넣습니다.  이후 부품들은 아래와 같이 연결합니다.

  • Jumper 10mm: Vcc - a1

  • Jumper  8mm: Gnd - a2

  • Jumper 10mm: j2 - Gnd

  • Jumper  8mm: j5 - Vcc

  • Jumper FM: RTC.Vcc - Vcc

  • Jumper FM: RTC.Gnd - Gnd

  • Jumper FM: RTC.CLK - a6

  • Jumper FM: RTC.DAT - a7

  • Jumper FM: RTC.RST - a8

  • Jumper FM: TM1637.Vcc - Vcc

  • Jumper FM: TM1637.Gnd - Gnd

  • Jumper FM: TM1637.CLK - a11

  • Jumper FM: TM1637.DIO - a13

RTC: Real-time Clock

TM1637: 4 digit LED tube




보드 준비 및 라이브러리 설치



소스 코드

#include 
#include 
#include 
#include 

const int MAX_CONNECT_TIME = 300;
const int QUERY_INTERVAL = 3000;

const char* ssid = "공유기 ID";
const char* password = "공유기 비번";

const char* host = "www.timeapi.org";
const int httpsPort = 80;
const String url = "/utc/now";

// TM1637 LED tube pin
const int led_clk_pin = 2;
const int led_io_pin  = 4;

// Realtime Clock pin
const int rt_ce_pin  = 14; 
const int rt_io_pin  = 12; 
const int rt_clk_pin = 13; 

TM1637Display display(led_clk_pin, led_io_pin);
DS1302 rtc(rt_ce_pin, rt_io_pin, rt_clk_pin);

void setup() {
  Serial.begin(9600);

  display.setBrightness(0x0f);

  rtc.writeProtect(false);
  rtc.halt(false);

  Serial.print("connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
}

int tick_count = 0;
bool display_dots = false;
void displayTime() 
{
  uint8_t data[] = { 0b00000000, 0b00000000, 0b00000000, 0b00000000 };

  Time t = rtc.time();

  int hr_lo = t.hr % 10;
  int hr_hi = (t.hr - hr_lo) / 10;

  if (hr_hi < 1) data[0] = display.encodeDigit(0);
  else data[0] = display.encodeDigit(hr_hi);

  if (hr_lo < 1) data[1] = display.encodeDigit(0);
  else data[1] = display.encodeDigit(hr_lo);
  
  int min_lo = t.min % 10;
  int min_hi = (t.min - min_lo) / 10;

  if (min_hi < 1) data[2] = display.encodeDigit(0);
  else data[2] = display.encodeDigit(min_hi);

  if (min_lo < 1) data[3] = display.encodeDigit(0);
  else data[3] = display.encodeDigit(min_lo);

  tick_count++;
  if (tick_count >= 5) {
      tick_count = 0;
      display_dots = ! display_dots;
      if (display_dots) data[1] = data[1] | 0b10000000;
  }
  
  display.setSegments(data);
}

int time_out = 0;
int query_count = 9999;

void loop() {
  displayTime();
  
  time_out++;
  if (WiFi.status() != WL_CONNECTED) {
    if (time_out > MAX_CONNECT_TIME) {
      time_out = 0;
      
//      Serial.print("connecting to ");
//      Serial.println(ssid);
//      WiFi.begin(ssid, password);
    }
    
    Serial.println("WiFi is not ready.");
    delay(100);
    return;
  }

  time_out = 0;

  query_count++;
  delay(100);

  if (query_count < QUERY_INTERVAL) return;

  query_count = 0;

//  Serial.println("");
//  Serial.println("WiFi connected.");
//  Serial.println("IP address: ");
//  Serial.println(WiFi.localIP());

  WiFiClient client;
//  Serial.print("connecting to ");
  Serial.println(host);
  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed.");
    delay(1000);
    return;
  }

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: BuildFailureDetectorESP8266\r\n" +
               "Connection: close\r\n\r\n");

  // Read Header
  while (client.connected()) {
    String line = client.readStringUntil('\n');
    if (line == "\r") break;
  }
  
  // Read Body
  if (client.connected()) {
    String line = client.readStringUntil('\n');

    // Korean local time need to add 9 hours.
    String hour = line.substring(11,13);
    String minute = line.substring(14,16);
    String second = line.substring(17,19);
    
    Time t(2016, 1, 1, (hour.toInt() + 9) % 24, minute.toInt(), second.toInt(), Time::kSunday);
    rtc.time(t);
  }
}
  • NodeMCU의 경우 함수 실행에 시간이 오래 걸리면 리부팅이 계속 진행되는 현상이 있었습니다.  그 때문에 코드가 조금 복잡해졌습니다.


'프로그래밍 > Arduino & IoT' 카테고리의 다른 글

Orange Pi Zero 사용 후기  (0) 2016.12.01
미아 방지기 만들기  (0) 2016.10.06
스스로 시간을 맞춰주는 인터넷 시계  (0) 2016.10.02
중국산 Arduino YUN shield 테스트 실패  (0) 2016.10.02
NodeMCU 프로그래밍  (0) 2016.09.23
자전거 안전등 #2  (0) 2016.09.22

Posted by 류종택