#author("2022-09-18T15:21:25+09:00","siio","siio")
#author("2022-09-18T15:21:38+09:00","siio","siio")
[[How2Computing]]

-これをLinuxで動かす方法は[[FT245RL_Linux:http://is.ocha.ac.jp/~siio/index.php?FT245RL_Linux]]を参照のこと
-これをRaspberry Piで動かす方法は[[FT245RL_RaspberryPi:http://is.ocha.ac.jp/~siio/index.php?FT245RL_RaspberryPi]]を参照のこと
--pythonに関する記述が新しいので、Raspberry Piのガイドもチェックしてください



*FTDI社USB-8ビットパラレル変換器 FT245RL を Mac OS X で使う [#a6c677ef]

秋月電子で購入.一個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モードのサンプルプログラムだった.

**インストールとテストの方法 [#q9142ba0]

+http://www.ftdichip.com/Drivers/D2XX/MacOSX/D2XX1.2.2.dmg
をダウンロードして内容をどこかにコピーする.

--追記:現在の最新版は,http://www.ftdichip.com/Drivers/D2XX.htm から確認可能.
+libftd2xx.0.1.0.dylibを/usr/local/libにコピー 
--cp D2XX/bin/libftd2xx.0.1.0.dylib /usr/local/lib
+バージョン名を外した名前のシンボリックリンクを作っておく
--cd /usr/local/lib
--ln -sf libftd2xx.0.1.0.dylib libftd2xx.dylib

Samplesのディレクトリの中に,サンプルプログラムが多数ある.
Samplesの中でmakeすると全部コンパイルされる.それぞれのディレクトリで個別にmakeしても良い.
たとえば,bitmodeのプログラムは,1バイトの値を出力して,読み込むサンプル.


**ハードウェアを作ってテストする [#h2cbee4b]

ブレッドボードの上に,LEDとスイッチを作って,接続した.

#ref(DSC_0028s.jpg);

このスイッチを押すと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に失敗することへの対策 [#n3938e1d]

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つです。

+VCPのドライバを削除する&br;
これを行うには、参考リンクのマニュアルPDFにしたがって、 
 sudo rm -r /System/Library/Extensions/FTDIUSBSerialDriver.kext
 sudo rm -r /Library/Receipts/FTDIUSBSerialDriver.kext
などとします。
--普通は、ArduinoとFT245RLを1つのコンピュータで同時に使うことは無いので、
ドライバを外しても良いと思います。
--Arduinoも使わないといけない場合、
FTD社のVCPドライバを使わないArduinoを使うという手もあります。
最近のArduino (Arduino Uno, Arduino MEGA 2560)は、
AtmelのATmega8U2チップにファームウェアを搭載しUSBシリアル変換を実現しています。
これは、標準のCDCクラスとして動作するので、
MacおよびLinuxではドライバーは必要なくなっています。
これらを使うことで、VCPドライバとの衝突はなくなります。

--VCPドライバを削除してもエラーコード3が出る場合
カーネル拡張モジュールを確認し、全てアンロードしてみる。
[参考]http://www.oversea-pub.com/free/environment/2083.html
 kextstat|grep FTDI
 140 0 0xffffff7f81660000 0x8000 0x8000 com.FTDI.driver.FTDIUSBSerialDriver (2.2.18) <127 36 5 4 3 1>
 141 0 0xffffff7f80f1f000 0x7000 0x7000 com.apple.driver.AppleUSBFTDI
 sudo kextunload -bundle com.FTDI.driver.FTDIUSBSerialDriver
 sudo kextunload -bundle com.apple.driver.AppleUSBFTDI

+チップのVID,PIDを変更する&br;
マニュアルのどこかに書いてあります。(試していません)



**追記:なぜかFT_Get Bit Modeがエラーを返す [#s6d1a938]

久々にこのプログラムを最新版ライブラリで試してみました.
するとどういうわけか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);
 }

**参考リンク [#bd5552b9]
-http://akizukidenshi.com/catalog/g/gK-01799/
//-http://akizukidenshi.com/catalog/items2.php?p=1&q=FT245RL
-http://www.ftdichip.com/Drivers/D2XX.htm
-http://www.ftdichip.com/Support/Knowledgebase/index.html
-http://www.ftdichip.com/Support/Documents/InstallGuides/Mac_OS_X_Installation_Guide.pdf
-http://ore-kb.net/hard/BitBang/

**番外編:Pythonから動かしてみる [#va3c15e9]
+上記のドライバをダウンロードする。
+https://github.com/snmishra/ftd2xx からPython用のラッパーをダウンロードする。
+ダウンロードすると ftd2xx-git1/setup.py があるのでインストールする。
--python setup.py build
--python setup.py install
+プログラムの中で import ftd2xx とすれば使える!
--サンプルは無さそうなので、 ftd2xx-git1/ftd2xx/ftd2xx.py などを見ながら自力で頑張る。

***上で用意したハードウェアのLEDを光らせるプログラム [#e08a45e0]

 #!/usr/bin/python
 # -*- coding:utf-8 -*-
 
 #DB0に取り付けたLEDを1秒ごとに点滅させるプログラム
 
 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は1バイトで受け取る、例:b'\xFF'
     ftd2xx.FTD2XX.write(ftHandle, data) 
 
 def ft245close(ftHandle):
     if ftHandle:
         ft245write(ftHandle, b'\x00')
         ftd2xx.FTD2XX.close(ftHandle)
         ftHandle = None
         print 'Closed device'
 
 #ここから実行される
 ftHandle = ft245open()

 
 #control-cを押したら終了
 try:
   while 1:
     ft245write(ftHandle, b'\x01')
     print("on")
     time.sleep(1)
     ft245write(ftHandle, b'\x00')
     print("off")
     time.sleep(1)
 except KeyboardInterrupt:
   ft245close(ftHandle)

*** readする [#d8c0968d]
 ftd2xx.FTD2XX.purge(self.ft_handle)
 data = ftd2xx.FTD2XX.read(self.ft_handle, 1)

とすると、dataの中にreadした値が入ります。
repr(data)とやるとうまくいくかもしれないです。

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS