2023年の6月に「PSoC4 : UART + Capsense Tuner」の記事をアップしたのですが、10月になって気がつくと、こっそりアップデートしていて、6月時点のプログラムでは文字化けがたくさん起こりました。
シリアル通信で、タッチの情報を出力していたのですが、けっこうな頻度で文字化けしました。
文字化けのタイミングを観察すると、タッチセンサのスキャンをすると割り込みが入るようで、UARTでデータを送る間にその割り込みが入ると、通信速度が合わなくなる感じです。6月の時点ではその割り込みをブロックしてくれる「Cy_SCB_UART_PutArrayBlocking」関数が使われているだけでしたが、10月には送信完了待ちの処理が追加されていました。
ModusToolBoxの「CAPSENSE Tuner」に読み込むだけだとこれでよいのですが、ArduinoUnoで使えるようにしたく、「SoftwareSerialでPSoCとシリアル通信をして、ArduinoのハードウェアシリアルでPC側に表示する」と考えました。
SoftwareSerialは、ArduinoUnoだと「57600bps」が最大なのか、それ以上で通信するとうまくいきません。そこで、57600bpsで受信したデータを、115200bpsでPCに送信するようにしました。逆にPCへの送信側を遅くすると、その間に受信したデータがバンバン届くので、取りこぼすだろうなと思います。
どんなデータが届くのか、Arduino側でデータを見たのですが、1つのタッチボタンの情報だけなのに、94バイトもありました。プログラムを調べてみるとタッチボタンの場合、センサの数に関係なく共通した情報が24バイト、センサ1つごとに56バイトが連続し、その後にタッチ情報(欲しい部分)が10バイト連続します。
ボタン1つの場合、欲しいタッチ情報までは、24+56バイト進んで、次の10バイトを読みます。
ボタン2つの場合、欲しいタッチ情報までは、24+56+56+10バイト進んで、次の10バイトを読みます。
プログラムで計算すると、以下のようになりました。
int commonText_size = 24; int widgetContext_size = 56; int sensorContext_size = 10; //1つ目のタッチ情報先頭までの計算 uint16_t address1 = commonText_size + (widgetContext_size * 2) + (sensorContext_size * 0); //2つ目のタッチ情報先頭までの計算 uint16_t address2 = commonText_size + (widgetContext_size * 2) + (sensorContext_size * 1);
以下のプログラムは、3つのタッチボタンの情報をArduinoのソフトウェアシリアル通信(57600bps)で読み出し、同じくArduinoからシリアル通信(115200bps)でPCに表示するプログラムです。
#include <SoftwareSerial.h>
SoftwareSerial mySerial(3, 2); // RX, TX
uint8_t buff[500];
int last_buff[2];
int pos;
int tc = 3;
typedef struct {
unsigned int raw;
unsigned int bsln;
unsigned int diff;
uint8_t status;
uint8_t negBslnRstCnt;
uint8_t idacComp;
uint8_t bslnExt;
} sensor_context;
typedef struct {
sensor_context sensorContext[3];
} cy_stc_capsense_tuner_t;
cy_stc_capsense_tuner_t capsense = {
.sensorContext = {
{
/* Button0 */
.raw = 0u,
.bsln = 0u,
.diff = 0u,
.status = 0u,
.negBslnRstCnt = 0u,
.idacComp = 32u,
.bslnExt = 0u,
},
{
/* Button1 */
.raw = 0u,
.bsln = 0u,
.diff = 0u,
.status = 0u,
.negBslnRstCnt = 0u,
.idacComp = 32u,
.bslnExt = 0u,
},
{
/* Button2 */
.raw = 0u,
.bsln = 0u,
.diff = 0u,
.status = 0u,
.negBslnRstCnt = 0u,
.idacComp = 32u,
.bslnExt = 0u,
} }
};
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(115200);
// while (!Serial) {
// ; // wait for serial port to connect. Needed for native USB port only
// }
mySerial.begin(57600);
}
void loop() {
while (mySerial.available() > 0) {
uint8_t c = mySerial.read();
if (c == 0x0a && last_buff[0] == 0x0d) {
pos = 0;
} else if (c == 0xFF && last_buff[0] == 0xFF && last_buff[1] == 0x00) {
int commonText_size = 24;
int widgetContext_size = 56;
int sensorContext_size = 10;
for (int i = 0; i < tc; i++) {
uint16_t ad = commonText_size + (widgetContext_size * tc) + (sensorContext_size * i) -1;
capsense.sensorContext[i].raw = (buff[++ad]) | (buff[++ad] << 8);
capsense.sensorContext[i].bsln = (buff[++ad]) | (buff[++ad] << 8);
capsense.sensorContext[i].diff = (buff[++ad]) | (buff[++ad] << 8);
capsense.sensorContext[i].status = (buff[++ad]);
capsense.sensorContext[i].negBslnRstCnt = (buff[++ad]);
capsense.sensorContext[i].idacComp = (buff[++ad]);
capsense.sensorContext[i].bslnExt = (buff[++ad]);
Serial.print(capsense.sensorContext[i].diff); //近接の数値
Serial.print(",");
Serial.print(capsense.sensorContext[i].status); //タッチのオンオフ(0か1)
Serial.print(",");
}
Serial.println();
} else {
buff[pos] = c;
pos++;
}
last_buff[1] = last_buff[0];
last_buff[0] = c;
}
}