Seeeduino XiaoでSPI通信をさせてみたくて、手元に落ちていた秋月電子のLPS331APモジュール(AE-LPS331)を動かしてみました。このモジュールはすでに販売終了していて秋月電子のWebサイトには資料の掲載がなく、資料を探すのに少々苦労しました。
動作させるにあたって、LPS331APモジュール上の半田ジャンパ(I2Cのプルアップ用)を外して以下の接続を行いました。
信号名 | AE-LPS331ピン番号 | Seeeduino Xiao接続先 | 備考 |
VDD | 1(1.71〜3.6V) | 3V3 | Xiao⇒LPS331で電源供給 |
SPC | 2 | SCK | SPIクロック |
SDI | 3 | MOSI | SPIデータ(Xiao⇒LPS331) |
SDO | 4 | MISO | SPIデータ(LPS331⇒Xiao) |
CS | 5 | D1 | チップセレクト |
GND | 8 | GND | GND |
Seeeduino Xiaoの開発環境はArduino環境を使用しました。環境はSeeed Studioのページの書いてある通りにセットアップしました。(今考えれば CircuitPython で良かったのかもしれません)
LPS331APを動かすソースコードはGoogle検索で見つかった光永 法明先生のページの「ST micro のデジタル気圧センサ LPS331AP を使う(SPI接続)」という記事に掲載されているものをそのまま使わせて頂きました。(LPS331APを動かすのが目的ではなく、SPIの信号を出すのが目的なので・・・)
実際には、下記の通り、CS端子(SS端子)の設定の変更とLEDを点滅させるコードを追加しています。
#include <SPI.h>
const int LPS331AP_CS = 1;
int _SS = 1; // ~CSをD1に接続
const byte LPS331AP_ADDR = B1011100; // SA0 = GND
//const byte LPS331AP_ADDR = B1011101;// SA0 = VDD_IO
const byte LPS331AP_WHOAMI = 0x0f;
const byte LPS331AP_CTRL1 = 0x20;
const byte LPS331AP_CTRL2 = 0x21;
const byte LPS331AP_CTRL3 = 0x22;
const byte LPS331AP_P_LL = 0x28;
const byte LPS331AP_P_L = 0x29;
const byte LPS331AP_P_H = 0x2A;
const byte LPS331AP_T_L = 0x2B;
const byte LPS331AP_T_H = 0x2C;
const byte LPS331AP_RW = 0x80;
const byte LPS331AP_MS = 0x40;
void LPS331AP_write(byte reg, byte val)
{
digitalWrite(LPS331AP_CS, LOW);
SPI.transfer(reg);
SPI.transfer(val);
digitalWrite(LPS331AP_CS, HIGH);
}
byte LPS331AP_read(byte reg)
{
byte ret = 0;
digitalWrite(LPS331AP_CS, LOW);
SPI.transfer(reg | LPS331AP_RW);
ret = SPI.transfer(0);
digitalWrite(LPS331AP_CS, HIGH);
return ret;
}
void setup() {
digitalWrite(_SS, HIGH);
pinMode(_SS, OUTPUT);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV8); // 8MHz/8 = 1MHz; (max 10MHz)
Serial.begin(115200);
while (!Serial) {}
Serial.println(LPS331AP_read(LPS331AP_WHOAMI), HEX); // should show BB
LPS331AP_write(LPS331AP_CTRL1, B10010000);
// |||||||+ SPI Mode selection
// ||||||+- DELTA_EN
// |||||+-- BDU: block data update
// ||||+--- DIFF_EN: interrupt circuit enable
// |+++---- ODR2, ODR1, ODR0 (1Hz)
// +------- PD: 0: power down, 1: active
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
long P;
short T;
float p, t;
P = LPS331AP_read(LPS331AP_P_H);
P = (P << 8) | LPS331AP_read(LPS331AP_P_L);
P = (P << 8) | LPS331AP_read(LPS331AP_P_LL);
T = LPS331AP_read(LPS331AP_T_H);
T = (T << 8) | LPS331AP_read(LPS331AP_T_L);
p = P;
p = p/4096.0;
t = T;
t = 42.5 + t/480.0;
Serial.print(P); // pressure (reading)
Serial.print(" ");
Serial.print(T); // temperature (reading)
Serial.print(" ");
Serial.print(p); // pressure in [mbar]/[hPa]
Serial.print(" ");
Serial.println(t); // temprerature in [`C]
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
で、動かしてみたのですが、理由がよくわかりませんが、Arduino環境のシリアルモニタでは1秒程度で表示が止まってしまいます。不思議なことに、
$ tail -f /dev/ttyACM0
4124716 -5507 1007.01 31.03
4124388 -5508 1006.93 31.02
4124483 -5508 1006.95 31.02
4124639 -5496 1006.99 31.05
4124199 -5532 1006.88 30.98
4124532 -5506 1006.97 31.03
4124496 -5508 1006.96 31.02
:
とすると、問題なく動作し続けるのですが・・・。
これに嵌って、余計な時間を費やしてしまいました。