1. 概要
液晶のついていないタッチスクリーンだけの情報をRaspberry Piで受け取る方法です。
タッチスクリーンは抵抗皮膜型のものを使用し、コントローラとしてASA7843を使用します。
コントローラとRaspberry Piの通信はSPIで、プログラムはNode.jsです。
2. 環境、使用機器
- Raspberry Pi 3 (Rasbpian Stretch)
- 4線抵抗膜型タッチスクリーン(4.3インチ)
- 1.25mmピッチ4P、FFCコネクタ
- http://www.aitendo.com/product/16196
- タッチコントローラモジュールADS7843
- 1.0mmピッチ4ピンFFCコネクタ(下接点)
- http://www.aitendo.com/product/2308
※ 上記のaitendoのモジュールにFFCのコネクタがついていますが、タッチスクリーンのFFCとピッチが合わないのでコネクタは使わずモジュールにピンソケットを追加して使用しています。
3. 参考サイト
-
- 下の方に「ESP にタッチパネルを SPI 接続する」という章があります
- タッチスクリーンとADS7843の仕組みの勉強とArduinoプログラムの参考にしました。
-
Getting started with SPI & analog input in NodeJS using Raspberry Pi and MCP3008 | Mikael Levén
- Raspberry PiでSPIを使う参考にしました。
4. まずArduinoでテストしてみる
4.1 配線
ADS7843 | Arduino Uno |
---|---|
CS | 10(SS) |
DOUT | 12(MISO) |
DIN | 11(MOSI) |
DCLK | 13(SCK) |
5V | 5V |
GND | GND |
4.2 プログラム
参考サイト(https://www.ei.tohoku.ac.jp/xkozima/lab/espTutorial2.html)のプログラムを元に以下の変更を加えました。
- CSのピンを
15
から10
に変更 -
SPI.setFrequency(1000000ULL);
がArudino UnoにないのでSPI.setClockDivider(SPI_CLOCK_DIV8);
に変更
#include <SPI.h>
//#define CS 15
#define CS 10
#define PEN 5
int Count = 0;
void setup() {
// debug output
Serial.begin(115200); delay(100);
Serial.println("");
Serial.println("*** esp_touthPanel ***");
// SPI settings (SCK, MISO, MOSI, CS=IO15)
pinMode(CS, OUTPUT);
digitalWrite(CS, HIGH);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
// SPI.setFrequency(1000000ULL); // max 2MHz
SPI.setClockDivider(SPI_CLOCK_DIV8);
// D5 for PEN
pinMode(PEN, INPUT);
}
void loop() {
int x, y;
if (touchPanel(x, y)) {
if (Count++ % 1000 == 0) {
Serial.print(x), Serial.print(", "), Serial.println(y);
}
}
}
bool touchPanel(int &x, int &y) {
if (digitalRead(PEN) == HIGH) {
// if not pen-down, return false
return false;
}
else {
// get data from ADS7843
unsigned char dataOut[3], dataIn[3];
// X-axis (X+)
dataOut[0] = 0x94; dataOut[1] = 0x00; dataOut[2] = 0x00;
digitalWrite(CS, LOW);
dataIn[0] = SPI.transfer(dataOut[0]);
dataIn[1] = SPI.transfer(dataOut[1]);
dataIn[2] = SPI.transfer(dataOut[2]);
digitalWrite(CS, HIGH);
x = (dataIn[1] * 256 + dataIn[2]) >> 3;
// Y-axis (Y+)
dataOut[0] = 0xD4; dataOut[1] = 0x00; dataOut[2] = 0x00;
digitalWrite(CS, LOW);
dataIn[0] = SPI.transfer(dataOut[0]);
dataIn[1] = SPI.transfer(dataOut[1]);
dataIn[2] = SPI.transfer(dataOut[2]);
digitalWrite(CS, HIGH);
y = (dataIn[1] * 256 + dataIn[2]) >> 3;
// return true
return true;
}
}
シリアルモニタでデータが取得できることを確認します。
5. Raspberry Pi 3で動かす
5.1 配線
ADS7843 | Raspberry Pi |
---|---|
CS | GPIO8 (CE0) / GPIO7 (CE1) |
DOUT | GPIO9 (MISO) |
DIN | GPIO10 (MOSI) |
DCLK | GPIO11 (SCLK) |
5V | 5V |
GND | GND |
5.2 プログラム
参考サイト(https://mikaelleven.wordpress.com/2015/12/13/getting-started-with-spi-analog-input-in-nodejs-using-raspberry-pi-and-mcp3008/ )を参考に以下の2点を変更しました。
- 1. spiTransfer()の形が変わったため修正
var recieveBuffer = rpio.spiTransfer(sendBuffer, sendBuffer.length);
var recieveBuffer = newBuffer(8);
rpio.spiTransfer(sendBuffer, recieveBuffer, sendBuffer.length);
- 2.
bcm2835_init: gpio mmap failed: Cannot allocate memory
で止まる問題を解決- 同じようなissueが
- 解決方法
-
rpio.init({gpiomem: false});
を宣言しました。 - サイトに書いてありました(https://github.com/jperkin/node-rpio#gpiomem)
-
var rpio = require('rpio');
var pin = 15;
var begin = function(){
rpio.spiBegin();
rpio.spiChipSelect(0); // 24番ピン(SPI0 CE0)に接続
rpio.spiSetCSPolarity(0, rpio.LOW) // ADS7843はActive-Low
};
var getValueX = function(){
var sendBuffer = new Buffer([0x94, 0x00, 0x00]); //
var recieveBuffer = new Buffer(8); // sendしたバイト数と同じバイト数返ってくる
rpio.spiTransfer(sendBuffer, recieveBuffer, sendBuffer.length);
var junk = recieveBuffer[0],
MSB = recieveBuffer[1],
LSB = recieveBuffer[2];
var value = (((MSB & 0x7f) << 8) + LSB)>>3; // 下位2バイトを3ビットシフトする
console.log('x :', value);
};
var getValueY = function(){
var sendBuffer = new Buffer([0xD4, 0x00, 0x00]);
var recieveBuffer = new Buffer(8); // sendしたバイト数と同じバイト数返ってくる
rpio.spiTransfer(sendBuffer, recieveBuffer, sendBuffer.length);
var junk = recieveBuffer[0],
MSB = recieveBuffer[1],
LSB = recieveBuffer[2];
var value = (((MSB & 0x7f) << 8) + LSB)>>3; // 下位2バイトを3ビットシフトする
console.log('y :', value);
};
var end = function(){
rpio.spiEnd();
};
rpio.init({gpiomem: false}); // SPI, I2Cを使用するため(実行時にsudoが必要)
rpio.open(15, rpio.INPUT, rpio.PULL_DOWN);
setInterval(function() {
var state = rpio.read(pin) ? 'high' : 'low';
console.log('Pin15 %s', rpio.read(15));
if(state == 'low'){
begin();
getValueX();
getValueY();
end();
}
},100);
sudo node test.js
で実行します。
実行するとコンソールに座標が表示されます。
5.3 SPIのトラブルシューティングの方法
- https://mikaelleven.wordpress.com/2015/12/10/troubleshooting-spi-on-raspberry-pi-nodejs/
- MOSIとMISOをループさせれば送ったものと同じものが返ってくる
5.4 追加のセンサを使う
IN3、IN4が空いているので別のアナログセンサを追加できます(配線が細かいですが)。
プログラム自体はほぼ同じで、0x94
、0xD4
となっていたところがIN3だと0xA4
、IN4だと0xE4
となります。