안드로이드 기기에서 CAN 및 UART 통신 사용

  집에 안쓰는 안드로이드 기기가 몇개 굴러다닌다.
사실 안드로이드 기기를 제어 용도로 사용해 보려고 보관 하고 있던 것들인데 바빠서 손을 못대고 있다가 이번에 건드려(?) 보았다.

  안드로이드 기기의 경우 구형 모델이라 할지라도 하드웨어 FPU에 멀티코어, 클럭 속도는 보통 1GHz이상으로 제어용으로 쓰기에는 차고 넘치는 성능이다.
심지어 GPS와 IMU센서에 나침반 센서도 내장되어 있다.
다만 안드로이드 어플리케이션이 Dalvik이라는 자바 가상 머신위에서 돌아가므로 CPU 성능이 좋다하더라도 제어 코드를 Dalvik위에서 돌아가는 Java 어플리케이션으로 만들면 원하는 만큼의 성능이 나오지 않을 수 도 있다.

  처음 접근은 Dalvik을 걷어내고 GUI는 리눅스 프레임버퍼에 직접 접근하는 QT나 SDL같은 라이브러리를 사용하려 했으나, 제어코드 몇 줄 돌릴려고 엄청난 삽질을 해야하는 상황이 발생 되었다.

  조금더 검색을 해보니 나와같은 변태들을 위해 구글에서 NDK라는 툴을 제공한다는걸 알게 되었다.
NDK (Native Development Kit)는 안드로이드 시스템의 리눅스레벨, 즉 Dalvik과 관련없이 안드로이드의 리눅스용으로 빌드하여 안드로이드 기기에서 동작 가능하도록 만들어 주는 개발 툴이다.
다만, 단독 사용은 안되고 라이브러리 형태로 만들어서 Dalvik용 어플리케이션에 종속되어 동작하는 구조이다.

  사용자 인터페이스 GUI는 Dalvik에서 돌아가는 Java 어플리케이션 (안드로이드 앱)으로 만들고 고속 혹은 Soft-Realtime 태스크가 필요한 제어의 코어 부분은 NDK로 만들어 접근하면 될듯 하다.

  외부 제어를 하려면 우선 외부와 통신을 해야하니 안드로이드 4.0부터 제공하는 USB-HOST기능을 활용하여 'USB to CAN' 및 'USB to UART' 하드웨어를 부착하여 통신 연동시험을 해봤다.
CAN이나 UART만 뚫려도 왠만한 제어 연동은 가능해 진다.

  우선 'USB to CAN' 컨버터 하드웨어를 하나 구했는데 요놈은 파이썬으로 동작시키는 용도로 드라이버에 접근하는 C API나 예제 소스하나 제공하지 않는다.
하는 수 없이 DLL 호출 및 USB transaction을 리버싱하여 USB control/bulk transfer 데이터 포멧을 찾아내 분석하고 NDK에 쑤셔 넣었다.
C와 Java를 왔다갔다 하며 코딩/디버깅 할라니 아주 지랄맞게 즐겁다.


[그림 1. 앱 및 NDK 동작]

[그림 2. PC 측 USB to CAN 연동 화면]

  시험은 안드로이드 기기에 'USB to CAN'하드웨어를 부착하고 NDK가 포함된 앱을 실행 시킨다 (그림 1). 반대쪽은 일반 PC에 같은 'USB to CAN'하드웨어를 부착하여 서로 CAN 패킷을 주고 받는 테스트를 하였다 (그림 2).
잘 되는군...
껌이네?
해보세요 정말정말 쉽습니다. 손가락만 까딱거리면 됩니다. 흐흐
혹시 이글 보시는 관리자분들, 실무자들한데 '봐~~ 쉽대잖아' 하시면 산채로 땅에 묻히는 수가 있습니다.

[그림 3. 실제 타겟 디바이스 XT-60]

[그림 3. USB to CAN 컨버터 부착]

  실 타겟 디바이스는 XT-60이라는 싸구려(?) 타블렛을 사용했다.
Soft-Realtime 태스크는 NDK상에서 생성하였으며 CAN 디바이스에 접근하여 CAN 패킷을 주고 받도록 구성하였는데 수[ms] 주기에 대해서도 잘 동작되었다.
나쁘지 않군...

  'USB to UART'도 NDK를 구성하여 테스트 해보았는데 잘 동작한다.
FTDI칩셋 기반은 리눅스용 디바이스 드라이버 소스가 공개되어있어 안드로이드 NDK용으로 포팅하는데 좀 수월했다.

내장된 센서가 많아 장비나 로봇에 직접 탑재해서 사용해도되고, 외부 점검/검사/제어용 펜던트등으로 활용해도 좋을꺼 같다.
카메라도 있으니 능력되면 영상기반 제어까지...

CAN, UART에 WIFI까지 연동이 되니 기쁘지 아니한가...

진수성찬


맛집이라고 소문난 식당 힘들게 찾아가 허기진 배를 움켜쥐고 줄서서 기다리다,
꾸역꾸역 앉았지만 밀려드는 손님들에 지쳐버린 종업원의 퉁명스런 반응과 뜻밖의 조우.
그리고 기대했던 소문난 맛 대신, 이걸 이렇게 비싸게 주고 여기까지 와서 먹어야 하나
이런 생각만을 가득 채워주는 별나고 맛나다는 음식 보다
편하고 부담없이 즐길 수 있는, 더 맛난 먹거리가 있다는걸 잠시 잊고 살았나 보다.

배고플 때 더도 말고 딱 라면 한 그릇.
출출할 때 두부 김치와 막걸리 한 사발.

2016/06/23 ~ 06/29 스위스 여행

이번엔 비행기로 10시간 넘게 가야하는 스위스로 여행을 다녀왔다.










































<> 스위스 여행 팁
 - 렌트카가 대부분 수동 차량입니다. 근 16년만에 수동 차량을 몰았는데 렌트카 주차장에서 십수번 엔진 꺼트려묵고 겨우 적응 되었습니다. 1년간 수동 차량을 몰았던 경험이 있어서인지 다행이 몸이 기억하고 있어서 운행이 가능했습니다. 경사가 가파르고 폭이 좁은 언덕길 운행이 적지 않으니 수동 차량 면허증이 있다 하더라도 자동 변속 차량 운전만 계속 해왔다면 잘 판단 하시길 바랍니다.
 - 안드로이드 스마트폰 사용에 능숙하다면 차 렌트하실때 GPS(네비게이션) 옵션을 빼고, 구글 오프라인 지도와 구글 지도에 기본 내장된 네비게이션 기능을 활용해 보세요. GPS 옵션 가격이 상당합니다. 돈 많다구요? 알아서 하세요.
 - 모바일 단말기의 데이터가 필요하다면 SALT라는 매장에서 Pre-Pay 유심 구입을 알아 보세요. 제가 여행 할 때 10프랑(약 12,300원)으로 10일간 데이터 무제한이었습니다. 유심 장착 후 20~30분이 지나도 인터넷이 안되면 APN 설정이 정상적으로 되지 않은 것이니 가까운 SALT매장에 들러 손봐달라고 하면 바로 됩니다.
 - 물가가 상상을 초월합니다. 라면과 햇반은 넉넉하게 준비해 가시고, 우리나라 대형 마트와 비슷한 COOP이나 MIGROS를 찾으면 그나마 저렴하게(하지만 여전히 비싼편) 먹거리 해결이 가능 할 겁니다. 금수저라구요? 식당 가세요.
 - 스위스 기상청(?) 날씨 예측이 나름 잘 맞는듯 합니다. 다음날 여행에 참고하세요.
 - 저렴하면서 비교적 시설 나쁘지 않은 호텔에 묵으려 한다면 IBIS BUDGET호텔을 추천 합니다. 라면용 온수와 햇반용 전자렌지 사용도 가능합니다. IBIS MESSE호텔도 있는데 IBIS BUDGET보다 가격이 좀 되고, 전자렌지가 없었습니다. 갑부라구요? 맘에 드는데 가세요.
 - 차를 빌리셨다면 그림젤패스(Grimselpass), 푸르카패스(Furkapass), 수스텐패스(Sustenpass) 고갯길은 꼭 가보세요. 두번 가세요. Need for Speed 게임에서만 보던 그림같은 광경이 눈앞에 펼쳐 집니다. 손대면 부러질 듯한 듬성듬성 심어진 플라스틱 안전봉 아래 수백미터 절벽의 고갯길을 운전하다 보면 심장이 쫄깃해 집니다.
 - 렌즈 교환식 카메라를 가져간다면 구할 수 있는 가장 넓은 광각 렌즈(어안 말고)를 가져 가세요. 눈으로 보는 장관이 뷰파인더에서는 많이 사라집니다. 스마트폰만 가져간다면 파노라마 촬영 기능이 있는지 확인하세요.
 - 그린델발트(Grindelwald)에서 비교적 저렴한 숙소를 찾아 헤매다 Downtown Lodge를 발견했는데 가격 대비 나쁘지 않았습니다. 샤워장과 화장실 및 주방을 공동으로 사용하는 도미토리 형태입니다. 한국 배낭족이 많았습니다. 3프랑(약 3~4천원)을 주면 고기 굽는 그릴과 석탄을 줍니다. COOP이나 MIGROS에서 스테이크용 소고기 덩어리 사다, 눈 쌓인 뾰족산을 배경으로 구워먹어 보세요. 맛이 좋습니다. 파란색 캔의 스위스산 맥주도 싸고 맛납니다.
 - 스위스 여름의 낮은 정말 깁니다. 밤 10시가 넘어가는데도 밖이 훤 합니다.
 - 속도 위반 벌금이 무지 쎄다고 합니다. 주의 하세요. 단속 카메라 모양은 우리나라와 다른거 같습니다. 차 빌릴때 제공한 한국 주소나 사용한 신용카드등으로 알아내어 어떻게 해서든 범칙금 고지서를 거주지로 보낸다고 합니다. 마지막날 여유 부리다 늦어서 공항 가는길 과속을 좀 했는데 범칙금 날라올꺼 땜시 현재 두려움에 부들부들 떨고 있습니다.
 - Victorinox 멀티툴(맥가이버 칼)은 스위스 현지 보다 우리나라 온라인 쇼핑몰이 더 쌉니다. 종류도 더 많습니다.

i.MX6Q (ARM Cortex-A9 Quad Core) Embedded Linux-Xenomai RTOS Porting

간만에 삽질좀 했다.
ARM Cortex-A9 쿼드코어 기반 AP인 i.MX6Q 프로세서에 Linux-Xenomai RTOS를 포팅해 봤다.
ARMv4/5기반의 오래된 ARM에만 포팅 해보다 나름 최근(?)의 성능 좋은 프로세서에 포팅작업을 하려다 보니 여러가지 삽질들이 좀 많았다.
우선 리눅스 커널 버전과 Xenomai 버전이 올라가면서 바닐라 커널의 Xenomai패치는 한결 수월해 졌으나, 커널에 Device-Tree라는 요상한게 생기고 Cortex-A9의 하드웨어 FPU인 VFPv3 및 NEON을 제대로 지원하는 툴체인을 빌드하느라 시간을 좀 많이 까묵었다 (툴체인 한번 빌드하는데 3~4시간, 커널 빌드하는데 30~40분).
마침내 커널 부팅되고 램디스크 마운팅 되고 Xenomai 어플리케이션 돌아가고...
드디어 1GHz 쿼드코어에서 돌아가는 RTOS가 만들어 졌다. 움하하...

<> 커널 부팅
------------------------------------------------------------------
Booting Linux on physical CPU 0x0
Linux version 3.10.32-xenokang (root@localhost.localdomain) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0) ) #1 SMP Wed Jun 15 10:43:26 KST 2016
CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine: Freescale i.MX6 Quad/DualLite (Device Tree), model: Freescale i.MX6 Quad SABRE Smart Device Board
Truncating RAM at 10000000-8fffffff to -7f7fffff (vmalloc region overlap).
Memory policy: ECC disabled, Data cache writealloc
PERCPU: Embedded 10 pages/cpu @815fc000 s18496 r8192 d14272 u40960
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 453136
Kernel command line: console=ttymxc0,115200 root=/dev/ram0 rw --no-log initrd=0x1E000000,16M ramdisk=32768
PID hash table entries: 4096 (order: 2, 16384 bytes)
Dentry cache hash table entries: 262144 (order: 8, 1048576 bytes)
Inode-cache hash table entries: 131072 (order: 7, 524288 bytes)
Memory: 1784MB = 1784MB total
Memory: 1786168k/1786168k available, 40648k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    vmalloc : 0xf0000000 - 0xff000000   ( 240 MB)
    lowmem  : 0x80000000 - 0xef800000   (1784 MB)
    modules : 0x7f000000 - 0x80000000   (  16 MB)
      .text : 0x80008000 - 0x80693ff4   (6704 kB)
      .init : 0x80694000 - 0x806ea840   ( 347 kB)
      .data : 0x806ec000 - 0x80717fa0   ( 176 kB)
       .bss : 0x80717fa0 - 0x807f9464   ( 902 kB)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
Hierarchical RCU implementation.
NR_IRQS:16 nr_irqs:16 16
sched_clock: 32 bits at 66MHz, resolution 15ns, wraps every 65075ms
I-pipe, 66.000 MHz clocksource
I-pipe, 396.000 MHz clocksource
CPU identified as i.MX6Q, silicon rev 1.2
Interrupt pipeline (release #5)
Console: colour dummy device 80x30
Calibrating delay loop... 1581.05 BogoMIPS (lpj=7905280)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
...
...
Switching to clocksource ipipe_tsc
NET: Registered protocol family 2
TCP established hash table entries: 16384 (order: 5, 131072 bytes)
TCP bind hash table entries: 16384 (order: 5, 131072 bytes)
TCP: Hash tables configured (established 16384 bind 16384)
TCP: reno registered
UDP hash table entries: 1024 (order: 3, 32768 bytes)
UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
Trying to unpack rootfs image as initramfs...
rootfs image is not initramfs (no cpio magic); looks like an initrd
Freeing initrd memory: 16384K (8e000000 - 8f000000)
hw perfevents: enabled with ARMv7 Cortex-A9 PMU driver, 7 counters available
I-pipe: head domain Xenomai registered.
Xenomai: hal/arm started.
Xenomai: scheduling class idle registered.
Xenomai: scheduling class rt registered.
Xenomai: real-time nucleus v2.6.4 (Jumpin' Out) loaded.
Xenomai: starting native API services.
Xenomai: starting POSIX services.
Xenomai: starting RTDM services.
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
NFS: Registering the id_resolver key type
Key type id_resolver registered
Key type id_legacy registered
jffs2: version 2.2. (NAND) ⓒ 2001-2006 Red Hat, Inc.
fuse init (API version 7.22)
msgmni has been set to 3520
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
imx-sdma 20ec000.sdma: initialized
Serial: IMX driver
2020000.serial: ttymxc0 at MMIO 0x2020000 (irq = 58) is a IMX
console [ttymxc0] enabled
...
...
RAMDISK: gzip image found at block 0
VFS: Mounted root (ext2 filesystem) on device 1:0.
devtmpfs: mounted
Freeing unused kernel memory: 344K (80694000 - 806ea000)
init started: BusyBox v1.22.1 (2016-06-15 10:43:42 KST)
starting pid 56, tty '': '/etc/init.d/rcS'

Please press Enter to activate this console.
starting pid 64, tty '': '-/bin/sh'
[root@imx6q /]#
[root@imx6q /]#
[root@imx6q /]# ls -al
drwxr-xr-x   17 0        0             1024 Jan  1 00:57 .
drwxr-xr-x   17 0        0             1024 Jan  1 00:57 ..
-rw-------    1 0        0                7 Jan  1 00:57 .ash_history
drwxr-xr-x    2 0        0             1024 Jun 15  2016 app
drwxr-xr-x    2 0        0             1024 Jun 15  2016 bin
drwxr-xr-x    5 0        0             2840 Jan  1 00:00 dev
drwxr-xr-x    3 0        0             1024 Jun 15  2016 etc
drwxr-xr-x    2 0        0             1024 Jun 15  2016 lib
lrwxrwxrwx    1 0        0               11 Jun 15  2016 linuxrc -> bin/busybox
drwx------    2 0        0            12288 Jun 15  2016 lost+found
drwxr-xr-x    2 0        0             1024 Jun 15  2016 nand
dr-xr-xr-x   64 0        0                0 Jan  1 00:00 proc
drwxr-xr-x    2 0        0             1024 Jun 15  2016 root
drwxr-xr-x    2 0        0             1024 Jun 15  2016 sbin
drwxr-xr-x    2 0        0             1024 Jun 15  2016 sdcard
dr-xr-xr-x   12 0        0                0 Jan  1 00:00 sys
drwxr-xr-x    2 0        0             1024 Jun 15  2016 tmp
drwxr-xr-x    5 0        0             1024 Jun 15  2016 usr
drwxr-xr-x    2 0        0             1024 Jun 15  2016 xenomai
[root@imx6q /]#
------------------------------------------------------------------


<> Xenomai latency 측정
------------------------------------------------------------------
[root@imx6q /xenomai/bin]#
[root@imx6q /xenomai/bin]# ./latency -t 0 -p 1000
== Sampling period: 1000 us
== Test mode: periodic user-mode task
== All results in microseconds
warming up...
RTT|  00:00:01  (periodic user-mode task, 1000 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD|     -3.043|     -2.028|      0.108|       0|     0|     -3.043|      0.108
RTD|     -3.152|     -1.927|     12.189|       0|     0|     -3.152|     12.189
RTD|     -3.013|     -1.902|      9.260|       0|     0|     -3.152|     12.189
RTD|     -3.109|     -1.935|     10.295|       0|     0|     -3.152|     12.189
RTD|     -3.006|     -1.879|     12.530|       0|     0|     -3.152|     12.530
RTD|     -3.028|     -1.947|     11.944|       0|     0|     -3.152|     12.530
RTD|     -3.175|     -1.940|     11.242|       0|     0|     -3.175|     12.530
RTD|     -3.102|     -1.975|      9.166|       0|     0|     -3.175|     12.530
RTD|     -3.104|     -1.950|     12.343|       0|     0|     -3.175|     12.530
RTD|     -3.091|     -1.958|     10.580|       0|     0|     -3.175|     12.530
RTD|     -3.089|     -1.955|     11.234|       0|     0|     -3.175|     12.530
RTD|     -3.003|     -1.973|     11.452|       0|     0|     -3.175|     12.530
RTD|     -3.086|     -1.920|      8.444|       0|     0|     -3.175|     12.530
RTD|     -3.124|     -1.925|     12.068|       0|     0|     -3.175|     12.530
RTD|     -3.185|     -1.953|     12.439|       0|     0|     -3.185|     12.530
RTD|     -2.973|     -1.955|     11.510|       0|     0|     -3.185|     12.530
RTD|     -3.079|     -1.955|     11.401|       0|     0|     -3.185|     12.530
RTD|     -3.096|     -1.955|      9.636|       0|     0|     -3.185|     12.530
RTD|     -3.056|     -1.958|     10.664|       0|     0|     -3.185|     12.530
RTD|     -3.081|     -1.877|     11.353|       0|     0|     -3.185|     12.530
RTD|     -2.958|     -1.872|     11.348|       0|     0|     -3.185|     12.530
RTT|  00:00:22  (periodic user-mode task, 1000 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD|     -3.099|     -1.958|     11.406|       0|     0|     -3.185|     12.530
RTD|     -3.190|     -1.917|     11.838|       0|     0|     -3.190|     12.530
RTD|     -3.104|     -1.958|     12.045|       0|     0|     -3.190|     12.530
RTD|     -3.033|     -1.940|      9.477|       0|     0|     -3.190|     12.530
RTD|     -2.980|     -1.892|     11.714|       0|     0|     -3.190|     12.530
^C---|-----------|-----------|-----------|--------|------|-------------------------
RTS|     -3.190|     -1.937|     12.530|       0|     0|    00:00:27/00:00:27
[root@imx6q /xenomai/bin]#
[root@imx6q /xenomai/bin]# ./latency -t 1 -p 1000
== Sampling period: 1000 us
== Test mode: in-kernel periodic task
== All results in microseconds
warming up...
RTT|  00:00:01  (in-kernel periodic task, 1000 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD|     -5.809|     -4.296|     -1.410|       0|     0|     -5.809|     -1.410
RTD|     -5.299|     -4.212|      7.689|       0|     0|     -5.809|      7.689
RTD|     -5.839|     -4.229|      5.860|       0|     0|     -5.839|      7.689
RTD|     -6.036|     -4.262|      6.257|       0|     0|     -6.036|      7.689
RTD|     -5.807|     -4.261|      4.067|       0|     0|     -6.036|      7.689
RTD|     -5.832|     -4.239|      5.286|       0|     0|     -6.036|      7.689
RTD|     -5.719|     -4.238|      6.799|       0|     0|     -6.036|      7.689
RTD|     -5.164|     -4.241|      6.147|       0|     0|     -6.036|      7.689
RTD|     -5.704|     -4.271|      5.980|       0|     0|     -6.036|      7.689
RTD|     -5.659|     -4.252|      4.008|       0|     0|     -6.036|      7.689
RTD|     -5.422|     -4.270|      3.601|       0|     0|     -6.036|      7.689
RTD|     -5.033|     -4.244|      5.464|       0|     0|     -6.036|      7.689
RTD|     -5.599|     -4.255|      6.290|       0|     0|     -6.036|      7.689
RTD|     -5.844|     -4.233|      5.909|       0|     0|     -6.036|      7.689
RTD|     -5.829|     -4.246|      6.244|       0|     0|     -6.036|      7.689
RTD|     -5.226|     -4.236|      3.805|       0|     0|     -6.036|      7.689
RTD|     -5.741|     -4.213|      4.822|       0|     0|     -6.036|      7.689
RTD|     -5.004|     -4.231|      3.398|       0|     0|     -6.036|      7.689
RTD|     -5.721|     -4.277|      5.842|       0|     0|     -6.036|      7.689
RTD|     -5.095|     -4.245|      6.205|       0|     0|     -6.036|      7.689
RTD|     -5.777|     -4.270|      4.114|       0|     0|     -6.036|      7.689
RTT|  00:00:22  (in-kernel periodic task, 1000 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD|     -5.394|     -4.246|      8.788|       0|     0|     -6.036|      8.788
RTD|     -5.677|     -4.195|      4.803|       0|     0|     -6.036|      8.788
RTD|     -5.715|     -4.183|      5.942|       0|     0|     -6.036|      8.788
RTD|     -5.798|     -4.256|      6.323|       0|     0|     -6.036|      8.788
RTD|     -4.904|     -4.132|      3.240|       0|     0|     -6.036|      8.788
RTD|     -5.564|     -4.200|      7.257|       0|     0|     -6.036|      8.788
RTD|     -5.779|     -4.227|      4.143|       0|     0|     -6.036|      8.788
RTD|     -5.693|     -4.237|      5.726|       0|     0|     -6.036|      8.788
RTD|     -5.572|     -4.254|      6.375|       0|     0|     -6.036|      8.788
RTD|     -5.067|     -4.142|      3.623|       0|     0|     -6.036|      8.788
^C---|-----------|-----------|-----------|--------|------|-------------------------
RTS|     -6.036|     -4.235|      8.788|       0|     0|    00:00:32/00:00:32
[root@imx6q /xenomai/bin]#
[root@imx6q /xenomai/bin]# ./latency -t 2 -p 1000
== Sampling period: 1000 us
== Test mode: in-kernel timer handler
== All results in microseconds
warming up...
RTT|  00:00:01  (in-kernel timer handler, 1000 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD|     -8.207|     -8.152|     -6.869|       0|     0|     -8.207|     -6.869
RTD|     -8.207|     -8.094|     -2.076|       0|     0|     -8.207|     -2.076
RTD|     -8.205|     -8.123|     -2.359|       0|     0|     -8.207|     -2.076
RTD|     -8.205|     -8.105|     -2.311|       0|     0|     -8.207|     -2.076
RTD|     -8.195|     -8.113|     -2.102|       0|     0|     -8.207|     -2.076
RTD|     -8.208|     -8.119|     -0.008|       0|     0|     -8.208|     -0.008
RTD|     -8.203|     -8.123|     -2.276|       0|     0|     -8.208|     -0.008
RTD|     -8.196|     -8.111|     -2.676|       0|     0|     -8.208|     -0.008
RTD|     -8.209|     -8.092|     -1.744|       0|     0|     -8.209|     -0.008
RTD|     -8.196|     -8.111|     -2.721|       0|     0|     -8.209|     -0.008
RTD|     -8.204|     -8.122|     -0.729|       0|     0|     -8.209|     -0.008
RTD|     -8.202|     -8.119|     -0.676|       0|     0|     -8.209|     -0.008
RTD|     -8.202|     -8.108|     -2.487|       0|     0|     -8.209|     -0.008
RTD|     -8.194|     -8.104|     -2.184|       0|     0|     -8.209|     -0.008
RTD|     -8.202|     -8.103|     -1.919|       0|     0|     -8.209|     -0.008
RTD|     -8.210|     -8.125|     -2.677|       0|     0|     -8.210|     -0.008
RTD|     -8.205|     -8.119|     -0.187|       0|     0|     -8.210|     -0.008
RTD|     -8.205|     -8.117|     -2.655|       0|     0|     -8.210|     -0.008
RTD|     -8.208|     -8.107|      0.115|       0|     0|     -8.210|      0.115
RTD|     -8.206|     -8.123|     -2.494|       0|     0|     -8.210|      0.115
RTD|     -8.193|     -8.102|     -2.380|       0|     0|     -8.210|      0.115
RTT|  00:00:22  (in-kernel timer handler, 1000 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD|     -8.209|     -8.118|     -0.395|       0|     0|     -8.210|      0.115
^C---|-----------|-----------|-----------|--------|------|-------------------------
RTS|     -8.210|     -8.114|      0.115|       0|     0|    00:00:23/00:00:23
[root@imx6q /xenomai/bin]#
------------------------------------------------------------------

UART, I2C, SPI, PWM, CAN, Ethernet, USB, SDIO, SATA, CAM, HDMI, 2D/3D Video 및 4개 1GHz 코어와 hardware-FPU를 탑재한 원칩 SoC에서 SMP를 지원하는 RTOS가 불과 1W 언저리에서 돌아간다... 우와, 막강이구먼.
안되는 제어가 없겠다.
어디에 쓰면 좋을까?

오래된 비디오폰 수리 및 컬러 LCD 개조

살고 있는 아파트에 20년이 넘은 비디오폰이 설치되어 있다.
당시에는 상당히 획기적이고 고가의 장비였을 것이다.
그 당시를 살아보지 않은 사람이라 잘 모른다. 크크크...
현관 카메라는 흑백이며, 비디오 디스플레이도 역시 흑백에 무려 브라운관 모니터.
고장이난듯 동작도 하지 않고 누렇게 변색된채로 거실벽에 큼지막하게 자리를 차지하고 있어 미관상 좋지도 않다. 하다 못해 외부 카메라 만이라도 동작해주면 좋으련만...
그래서 컬러 카메라에 LCD 모니터를 달아주는 개조를 해보기로 했다. 개조와 더불어 수리가 가능한 부분이 있으면 수리도 해주었다.


[참고 이미지]

뜯기전 사진을 찍지 않았는데 대충 분위기가 위 사진과 같다. 우리집은 벽지가 하얀색이라 누렇게 변색된게 나이 많이 먹은걸 그대로 보여주고 있었다.
수리 및 개조를 하려면 일단 뜯는다.


[비디오폰 탈거]

배선이 예상했던 것보다 무지하게 복잡하다. 신형으로 설치된 인터폰 배선과 얽혀있어 더 복잡해 보인다. NTSC용 동축 케이블을 제외하고 나머지는 모두 같은 종류의 선재를 사용해 구분이 되지도 않는다. 모든 선마다 라벨을 붙여주고 뜯어 낸다.


[비디오폰 본체]


[비디오폰 본체 메인보드]


[비디오폰 본체 단자대]


[현관 설치 카메라]

현관 밖에 설치되어 있는 카메라를 뜯어봤다. 카메라가 동작 되는지 전원 넣고 별도 모니터로 확인해 보니 게슴츠레 흑백 영상이 나오는가 싶더니 이내 화면이 깨지고 지글지글거린다. 다행히 카메라 모듈과 음성 모듈이 분리되어 있어 작업이 수월 했다. 기존에 붙어 있는 흑백 카메라 모듈을 들어 내고 컬러 카메라를 달아 준다.


[컬러 카메라 모듈]

일전에 아파트 CCTV 교체하면서 버려 놓은 카메라를 주워 놓았던걸 재 사용했다. 아파트 현관 천장에 반구 모양으로 달려있는 그 카메라에서 뜯은 것이다. 렌즈만 닦아 주니 잘 나오는데 왜 교체를 했는지 모르겠다. HD급으로 바뀌었나?...
여튼 아래와 같이 달아 준다.


[카메라 모듈 교체]

비디오폰 본체에는 아래 사진과 같이 상당히 컴팩트하게 잘 만들어진 브라운관 모니터가 달려 있다. 브라운관 모니터를 그 작은 공간에 잘 우겨 넣었다. 역시 공돌이들은 대단해...


[흑백 브라운관 모니터]

컬러 LCD 모니터는 비디오폰 연령대에 맞춰 'GoldStar' 할아버지를 달아 줬다. 그래도 나이대가 맞아야 잘 어울리겠지 하는 마음에서다.


[비디오폰과 비슷한 연세로 보이는 컬러 LCD 모니터]

LCD모니터는 오래된 캠코더에 모니터용으로 달려있던 것이다. 최근 기종을 달아 주려고 했으나 최근 LCD 모니터는 전원 및 입력 소스 선택이 리모컨 방식이거나 소프트 스위치 방식이라 전원이 들어 가자 마자 바로 동작 해야 하는 비디오폰 모니터 용도로 사용하기에 적합하지가 않다.
다만 좀 아쉬운건 LCD 크기가 작다는거...
이제 모두 가조립 하고 배선연결 후 동작 시험을 해본다.


[비디오폰 및 카메라 연동 시험]


[카메라 연동 확인]

잘 되는군...
어렸을적 내가 그림을 좀 잘 그렸었다.
잘 되는 것을 확인 했으니 다시 달아 준다.
달아 주기 전에 비디오폰 프레임을 모두 탈거하여 세제로 다시 닦아 준다. 닦아 주고 나니 누런끼가 살짝 줄어 들면서 좀 나아 졌다.


[재 장착]


[현관 카메라 모니터]

조립은 분해의 역순.
볼트가 몇개 남아도 당황하지 말고 침착하게 처음부터 다시...