指紋認証式電気錠の制作

きっかけ

ある事情によりかなり前から電気錠を作りたいと思っていたのですが、認証方式としてキーパッドによる暗証番号もしくはRFIDタグを用いた非接触認証を考えていました。しかしこれらの認証方式はハイテク感があまりなく、非接触の認証もやSuicaや各種電子マネーなど非接触ICカードの普及により珍しくないと思います。いよいよ作らないといけない時期になってきて、ふとデジットBlogの指紋スキャンモジュールの記事を発見してこれだ!と思いました。

この「GT-511C1」の製造元はADH Technology社で、CMOS光学センサや32ビットARMマイコンを搭載したモジュールです。SmackFinger 3.0という技術を搭載しており、このモジュール単体で20件までの指紋が登録でき、1:NのIdentify(識別)と1:1のVerify(検証)が可能です。

指紋認証を実現するには指紋の読み取りに加えて指紋の特徴検出技術が必要で、個人ですべてを実装するのはかなり敷居が高いです。一方、指紋認証自体はノートパソコンやスマートフォンで広く採用されており個人で作れたらいいなという憧れもあります。個人レベルの工作でもこのようなシステムを実用レベルで作れるという本当に良い時代になったと思います。

回路

このモジュールの制御にはUARTによるシリアル通信を使いますので、AVRやPIC、ArduinoといったUSARTインタフェースを持つマイコンで簡単に制御することができます。今回はATmega168を使いました。周辺回路としては、表示用の7セグメントLEDと動作音のための圧電スピーカーとソレノイド、スイッチを設けています。ソレノイドでロック機構を動作させます。ソレノイドは6VのものでFETで駆動します。

以下は回路図と実験中の様子です。

f:id:jptomoya:20140117223959p:plain

指紋認証式電気錠のメインボード

課題

制作してみて思ったことですが、まず3端子レギュレータを利用しましたが省電力の面で不利です。この回路だと電池動作は望めません。指紋スキャンモジュールのUARTインタフェースは電源電圧に関わらず3.3V系です。設計時の考えでは電源を6Vとし、3端子レギュレータを使って3.3Vに降圧して指紋モジュールとAVRの電圧を一致させて動作させればシリアル線を直結できるため都合が良いと考えました。しかし、μPC2933Bは無負荷時の電流が2mA程あるそうなので電池動作に向きません。例えばAVRを5Vで動作させてもTx側を分圧してからRxに繋げば相手が3.3Vでも問題ないでしょうし、Rxはそのまま繋いでもピンがHIGHと認識される最低保証電圧である0.6Vccを超えますのでこれも問題ありません。

またプログラムの開発過程で気づいたことですが、AVRのクロックに水晶を取り付けたものの、内蔵発振で十分動作したのであえて水晶を使う意味はないと思います。

これらを踏まえると、3端子レギュレータや水晶を省略すれば基板の小型化が可能で、ソレノイドは消費電流が大きいとはいえ間欠動作であるため電池運用の道も見えてきそうです。

行先表示の変換プログラム

現在電光掲示板(実物)を作ろうとしています。
表示するものがないとアレなのでネットに多く出回っている行先表示を扱いやすく変換するプログラムを書きました。出回っている行先表示を再現した画像はこのように、LEDの表示をモニタ上で再現するためにLED1個分で4ドット使いドット間は1ドットずつあいているのが一般的なようです。

電光掲示板を作るに先立って、この画像から元データを再現するプログラムを書きました。C#で書いてみるとやはり画像の扱いが非常に楽ですね。
変換プログラムはコンソールアプリで、画像ファイルをD&Dでも動作します。とりあえず223系などで使われている96x32ドットの行先表示のみに対応したつもりなので、289x97ドットの画像以外ははねのけます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace BitmapConv
{
    class Program
    {
        static void Main(string[] args)
        {
            Bitmap img;
            var outimg = new Bitmap(96, 32);
            var outputfilename = "output.bmp";
            int x, y;

            if (args.Length < 1)
            {
                Console.WriteLine("Usage: BitmapConv.exe [input file] [output file](optional)");
                Environment.Exit(0);
            }
            else if (args.Length == 2)
                outputfilename = args[1];

            try
            {
                img = new Bitmap(args[0]);

                if (img.Width != 289 || img.Height != 97)
                {
                    Console.WriteLine("Error: Input image size must be 289x97.");
                    img.Dispose();
                    Environment.Exit(0);
                }

                for (x = 0; x < 96; x++)
                    for (y = 0; y < 32; y++)
                        outimg.SetPixel(x, y, img.GetPixel(3 * x + 1, 3 * y + 1));
                img.Dispose();
            }
            catch (ArgumentException)
            {
                Console.WriteLine("There was an error." +
            "Check the path to the image file.");
                Environment.Exit(0);
            }

            outimg.Save(outputfilename);

            outimg.Dispose();
        }
    }
}

出力はこんな感じです。

UNIX V6のchmodはコンパイルがそのまま通る

小ネタですが、UNIX V6のs1\chmod.cを現代のコンパイラ(Visual C++ 2012)でコンパイルしてみました。UNIX V6といえば1975年にリリースされたPDP-11向けに書かれたコードですが、警告が出るもののどこも変更することなくコンパイルが通ります。
countを初期化しなかったり、'0'〜'7'が連続していることを想定したコードとなっていたりとかなり処理系依存なものとなっています。

main(argc, argv)
char **argv;
{
	register i, m;
	register char *c;
	int count;

	if(argc < 3) {
		printf("arg count\n");
		exit(1);
	}
	c = argv[1];
	m = 0;
	for(m=0; *c; c++) {
		if(*c < '0' || *c > '7') {
			printf("bad mode\n");
			exit(1);
		}
		m = (m<<3) | *c - '0';
	}
	for(i=2; i<argc; i++)
		if(chmod(argv[i], m) < 0) {
			count++;
			perror(argv[i]);
		}
	exit(count);
}

Microsoft(R) C/C++ Optimizing Compiler Version 17.00.60610.1 for x86
Copyright (C) Microsoft Corporation. All rights reserved.

chmod.c
c:\users\user\desktop\chmod.c(23) : warning C4700: 初期化されていないローカル変数 'count' が使用されます
Microsoft (R) Incremental Linker Version 11.00.60610.1
Copyright (C) Microsoft Corporation. All rights reserved.

/out:chmod.exe
chmod.obj