(これをLinuxで動かす方法はFT245RL_Linuxを参照のこと)
秋月電子で購入.一個980円. FTDI社のFT245RLにUSBコネクタ付けて,パスコンなど取り付けて, 使い易くした製品. FTDI社の製品は,USB-シリアル変換器チップで有名なシリーズであるが, これは,USB-シリアル変換に,バッファとパラレル入出力を付けたものらしい. FTDI社が配布している仮想シリアルドライバを使うと,シリアルデバイスとして バッファを読み書きできるが, 外部端子にタイミング信号を与えないとバッファからパラレル端子に入出力しない. 一方,FTDI社が配布しているライブラリーをインストールして呼び出すと, Bit-Bangモードという方式でお手軽にパラレル入出力できる. Big-Bangモードは,外部からバッファー・パラレル端子間の変換タイミング信号を 与えなくても,内部で定期的に更新してくれるモード.
FTDI社のページ http://www.ftdichip.com/Drivers/D2XX.htm から,各種プラットフォーム用のドライバ/サンプルプログラムが入手可能. ここからダウンロードしたうちの,Bit Modeのサンプルが, お手軽にパラレル入出力するためのBit-Bangモードのサンプルプログラムだった.
Samplesのディレクトリの中に,サンプルプログラムが多数ある. Samplesの中でmakeすると全部コンパイルされる.それぞれのディレクトリで個別にmakeしても良い. たとえば,bitmodeのプログラムは,1バイトの値を出力して,読み込むサンプル.
ブレッドボードの上に,LEDとスイッチを作って,接続した.
このスイッチを押すとLEDが光るプログラムを,bitmodeのサンプルを元に作ってみた. LEDはData 0 (LSBのビット) に,スイッチはData 4に接続している. (逆スラッシュ¥が疑問符?に化けているので注意)
/*
To build use the following gcc statement
(assuming you have the d2xx library in the /usr/local/lib directory).
gcc -o bitmode main.c -L. -lftd2xx -Wl,-rpath /usr/local/lib
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "../ftd2xx.h"
#include <unistd.h> //for usleep()
// Globals
FT_HANDLE ftHandle = NULL;
void ft245close()
{
if(ftHandle != NULL) {
FT_Close(ftHandle);
ftHandle = NULL;
printf("Closed device?n");
}
}
void ft245quit()//コントロールCで止められた時の修了処理
{
ft245close();
exit(1);
}
void ft245open()
{
FT_STATUS ftStatus;
ftStatus = FT_Open(0, &ftHandle);//接続されている0番目のデバイスを設定.
if(ftStatus != FT_OK) {
printf("FT_Open(0) failed = %d?n", ftStatus);
exit(1);
}
FT_SetBaudRate(ftHandle, 9600);//読み書きする周期を指定
//上位4ビットを入力に,下位4ビットを出力に,Bit-Bangモードに設定
ftStatus = FT_SetBitMode(ftHandle, 0x0F/*1=out 0=in*/, 1/*bit-bang mode on*/);
if(ftStatus != FT_OK) {
printf("Failed to set bit mode?n");
exit(1);
}
}
void ft245write( unsigned char data)//1バイト出力
{
DWORD dwBytesInQueue = 0;
FT_Write(ftHandle, &data, 1, &dwBytesInQueue);
}
unsigned char ft245get()//1バイト入力
{
FT_STATUS ftStatus;
unsigned char ucdata;
ftStatus = FT_GetBitMode(ftHandle, &ucdata);
if(ftStatus != FT_OK) {
printf("Failed to get bit mode?n");
exit(1);
}
else return(ucdata);
}
int main(void)
{
unsigned char data;
signal(SIGINT, ft245quit); // trap ctrl-c call quit fn
ft245open();
for(;;) {
data=ft245get();
printf("data=0x%X?n", data);
if ( (data & 0x10) ==0 )
ft245write(0x01);
else
ft245write(0x00);
usleep(100000L);
}
ft245close();
return 0;
}
openするときにエラーコード3で、エラーが返ってくることがありました。 USB接続をしないときはエラーコード2です。 USB接続を外すと、2が返ってきて、USBに挿すと3が返ってくる場合です。
同じコンピュータでArduinoを使ったことがある場合にも発生します。 これは、Arduinoをインストールしたときに、 FTD社のシリアル用ドライバがすでにインストールされていて、 これと衝突しているためです。 ArduinoのシリアルUSB変換器も、FTD社を使っているため、USBのVID, PIDが同一になってしまいます。
FTD社のチップを使うには、 このページで紹介しているD2XX (direct driver interface)の他に、 VCP (virtual COM port)というドライバの2種類があり、これらの2つは共存できません。 Arduinoを使ったか、もしくは、ほかのきかっけで、VCPドライバがインストールされてしまっていると、 そちらが先にこのチップの使用権を占有してしまっていて、openにエラーコード3で失敗するようです。 対策は、以下の2つです。
sudo rm -r /System/Library/Extensions/FTDIUSBSerialDriver.kext sudo rm -r /Library/Receipts/FTDIUSBSerialDriver.kextなどとします。
久々にこのプログラムを最新版ライブラリで試してみました. するとどういうわけかFT_Get Bit ModeがFT error code 4で失敗します.
その場合は,FT_Readを使ったらなんとかなりました. ft245get()の部分を以下のようにすると,同様に動くようです.
unsigned char ft245get()//1バイト入力
{
FT_STATUS ftStatus;
unsigned char ucdata;
int readsize=0;
FT_Purge( ftHandle, FT_PURGE_RX | FT_PURGE_TX); //clear receiver buffer
while(readsize==0) {
ftStatus = FT_Read(ftHandle, &ucdata, 1, &readsize);
if(ftStatus != FT_OK) {
printf("Failed to get bit mode. err %d\n", ftStatus);
exit(1);
}
}
return(ucdata);
}
# -*- coding:utf-8 -*-
#とりあえずこれでLEDが点滅します
import ftd2xx
import time
def ft245open():
ftHandle = ftd2xx.open(0)
ftd2xx.FTD2XX.setBaudRate(ftHandle, 9600)
ftd2xx.FTD2XX.setBitMode(ftHandle, 0x0F, 1)
return ftHandle
def ft245write(ftHandle, data):
#dataはStringで受け取る
ftd2xx.FTD2XX.write(ftHandle, data)
def ft245close(ftHandle):
if ftHandle:
ft245write(ftHandle, '0x00')
ftd2xx.FTD2XX.close(ftHandle)
ftHandle = None
print 'Closed device'
#ここから実行される
ftHandle = ft245open()
#Qを押したら終了
while 1:
ft245write(ftHandle, '0x01')
time.sleep(1)
ft245write(ftHandle, '0x00')
time.sleep(1)
ft245close(ftHandle)
ftd2xx.FTD2XX.purge(self.ft_handle) data = ftd2xx.FTD2XX.read(self.ft_handle, 1)
とすると、dataの中にreadした値が入ります。 repr(data)とやるとうまくいくかもしれないです。