Windows 10 Pro (v1909)
PYNQ-Z1 (Digilent) (以下、PYNQと表記)
PYNQ v2.5 Image
Vivado v2019.1 (64-bit)
Analog Discovery 2 (以下、AD2)
概要
- I2C(EMIO)を使用する
- XSDKにてI2Cの通信を実装する
- EEPROM versionの読込み
関連
-
borgThermo > 放射温度計 > 第一回: STM32L476とMLX96032の通信(I2C)
- MLX96032の情報はこちらを参考にする
参考
-
ZYBOのPSでI2Cを動かしてみた
- Todotaniのはやり物Log様
- 情報感謝です
こちらの記事を参考にPYNQ-Z1で試しました。
Block Design
IIC_0が追加されるので、Make Externalする。名前はIIC_0とした。
制約ファイル
ZYNQ-Z1用のプリセットファイル (PYNQ-Z1_C.xdc
)に記載されている、I2CのP16とP15をI/O portsに設定しておく (Run Synthesize後)。
3.3Vで使用するためLVCMOS33を選択した。
set_property IOSTANDARD LVCMOS33 [get_ports IIC_0_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports IIC_0_sda_io]
set_property PACKAGE_PIN P16 [get_ports IIC_0_scl_io]
set_property PACKAGE_PIN P15 [get_ports IIC_0_sda_io]
MLX90632
Zephyr RTOSの勉強時に購入した下記を使う。
EEPROM versionの読込み通信があり、それを用いてI2C動作を確認することとした。
MLX90632 放射温度計センサークリックボード [CLICK-IRThermo]
http://www.microtechnica-shop.jp/shopdetail/000000000108/disp_pc/
I2Cアドレスは0x3A
。
プルアップ抵抗は基板上のものをそのまま使用した(1kΩのプルアップ抵抗)。
接続
Arduino Connectorの右上にあるSCL, SDAを使用した。
https://reference.digilentinc.com/reference/programmable-logic/pynq-z1/reference-manual
の「17 Arduino/chipKIT Shield Connector」
Docs » PYNQ Libraries » Arduinoにも記載がある (I2C: SCL, SDA)。
- PYNQ-Z1 <--> MLX90632 [CLICK-IRThermo]
- 3V3 <--> 3V3
- GND <--> GND
- SCL <--> SCL
- SDA <--> SDA
XSDK
今回はPythonではなく、XSDKで実行する。
Python(PYNQ Library)でのI2C実行については不明である。
実装はこちらに紹介されているものに対して、書き込みを複数文字列で実行できるようにi2c_buffwrite()
を追加した。
# include "platform.h"
# include "xparameters.h"
# include "sleep.h"
# include "xiicps.h"
# include "stdio.h"
// I2C parameters
# define IIC_SCLK_RATE 100000 // clock 100KHz
# define MLX90632_ADDRESS 0x3A // 7bit address
# define IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID
XIicPs Iic;
int Init()
{
int Status;
XIicPs_Config *Config; /**< configuration information for the device */
Config = XIicPs_LookupConfig(IIC_DEVICE_ID);
if(Config == NULL){
printf("Error: XIicPs_LookupConfig()\n");
return XST_FAILURE;
}
Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);
if(Status != XST_SUCCESS){
printf("Error: XIicPs_CfgInitialize()\n");
return XST_FAILURE;
}
Status = XIicPs_SelfTest(&Iic);
if(Status != XST_SUCCESS){
printf("Error: XIicPs_SelfTest()\n");
return XST_FAILURE;
}
XIicPs_SetSClk(&Iic, IIC_SCLK_RATE);
printf("I2C configuration done.\n");
return XST_SUCCESS;
}
int i2c_buffwrite(XIicPs *Iic, u8* buff, u32 len, u16 i2c_adder)
{
int Status;
Status = XIicPs_MasterSendPolled(Iic, buff, len, i2c_adder);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
// Wait until bus is idle to start another transfer.
while(XIicPs_BusIsBusy(Iic)){
/* NOP */
}
return XST_SUCCESS;
}
int i2c_read(XIicPs *Iic, u8* buff, u32 len, u16 i2c_adder)
{
int Status;
Status = XIicPs_MasterRecvPolled(Iic, buff, len, i2c_adder);
if (Status == XST_SUCCESS)
return XST_SUCCESS;
else
return -1;
}
int main()
{
init_platform();
Init();
u8 wrbuff[] = { 0x24, 0x0B }; // Raed EEPROM version
u8 rdbuff[4];
u16 rawdata;
float temp;
while(1) {
i2c_buffwrite(&Iic, wrbuff, 2, MLX90632_ADDRESS);
i2c_read(&Iic, rdbuff, 2, MLX90632_ADDRESS);
usleep(1000*1000); // sleep 1sec (1000 x 1000us)
}
cleanup_platform();
return 0;
}
Analog Discovery 2(AD2)でのモニタ
上記の実装をデバッグ実行した。
下記のようにAD2で通信を確認できた。
少しひげがでているが、0x04, 0x87というEEPROM Versionが読取りできているようだ。
実使用時にはこのひげの対処が必要になるが、とりあえずPYNQからI2C通信はできるようにはなった。
PYNQ Library
https://discuss.pynq.io/t/how-to-use-i2c-with-pynq-z1/1039
上記の実装を試そうとしたが、PL.ip_dictが空だったので実施できなかった。