Interface 2015年4月号 第1部 第5章および第6章のプログラム

Dependencies:   USBDevice mbed

Information

FilterTest - Interface 2015年4月号 第1部 第5章 第6章 のソフトウェア

Program for Section 5 and 6 in April 2015 issue of Interface
(Japanese electronics magazine)

概要

このプログラムは、

  • ハイパスフィルタ、ローパスフィルタ、ノッチフィルタ

を行うFilterTestクラスと、波形をUSBシリアル通信でホストへ送信するmain関数で構成されています。

FilterTest.h, FilterTest.cpp

  • A-Dサンプリング - 1 kSPS
  • ハイパスフィルタ(遮断周波数 0.5 Hz、1次バターワース)
  • ローパスフィルタ(遮断周波数 30 Hz、2次バターワース)
  • ノッチフィルタ(中心周波数 50 Hz、2次)

main.cpp

  • データ送信レート - 1 kSPS
  • FilterTestクラスのインスタンスを生成
  • 処理開始メソッドを実行
  • メインループ - ポーリングにより、サンプリング、フィルタ処理完了フラグがセットされたら、
    USBシリアル通信経由で、ホストへ送信する

シリアル通信フォーマット

 (※)誌面ではパケットサイズ 64 byteとなっていますが、
    64 byteでは、PCのUSBドライバが 4096 byteまで保持し、波形が滑らかに描画できないため、
    Ver.1.0.2で、32 byteに変更しています。

  • 34byte固定長パケット方式
  • 波形データパケット1種類
波形データパケット
0x00パケットヘッダ(固定値0xAA)
0x01データ種別ID(0x01: 波形データ)
0x02パケット番号(0 - 99繰り返し)
0x03ペイロードサイズ(固定値30)
0x04 - 0x21波形データ(short, big endian)

Description

This contains FilterTest class and main function.

FilterTest class:

  • High pass filter, Low pass, Notch filter

Main function:

  • Send waveform to host via USB serial class.

FilterTest.h, FilterTest.cpp

  • A-D sampling - 1 kSPS
  • High pass filter - Cut off frequency 0.5 Hz, first order butterworth
  • Low pass filter - Cut off frequency 30 Hz, second order butterworth
  • Notch filter - Center frequency 50 Hz, second order

main.cpp

  • Data sending rate - 1 kSPS
  • Executing start procedure method
  • Main loop - sending waveform data via USB serial interface when detecting ready flag.

Packet format for USB serial interface

  • Packet size: 34 bytes(fixed)
  • One type of packet waveform packet
Waveform packet
0x00Packet header (0xAA (fixed))
0x01Data type ID (0x01: Waveform ID)
0x02Packet number (0 - 99)
0x03Payload size (30 (fixed))
0x04 - 0x21Waveform data (short, big endian)
Revision:
0:7a4d80e7ea81
Child:
1:4172c4324c2d
diff -r 000000000000 -r 7a4d80e7ea81 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Feb 21 19:28:57 2015 +0000
@@ -0,0 +1,170 @@
+/**
+ *  @file       Main.cpp
+ *  @brief      Send 1ch waveform data to PC via USB serial
+ *  @date       2015.02.22
+ *  @version    1.0.1
+ */
+#include "mbed.h"
+#include "USBSerial.h"
+#include "FilterTest.h"
+
+#define ON      (1)
+#define OFF     (0)
+
+#define LED_ON  (0)
+#define LED_OFF (1)
+
+#define BYTE_MASK     (0xFF)
+#define INT16_MAX     (32767)
+#define INT16_MIN     (-32768)
+
+#define SAMPLING_RATE (0.001)   /* A/D sampling rate (1ms) */
+
+#define PACKET_HEADER (0xAA)
+#define WAVEFORM_ID   (0x01)
+#define PACKET_SIZE   (64)
+#define DATA_NUM      (60)
+#define BUF_NUM       (2)
+#define CNTR_SIZE     (100)
+/*  [ Packet format ]                                           */
+/*        ----------------                                      */
+/*  0x00 | Header byte    | Fixed value (PACKET_HEADER:0xAA)    */
+/*  0x01 | Data type      | ID value    (0x01:Waveform)         */
+/*  0x02 | Packet counter | Count value (0to99 < CNTR_SIZE:100) */
+/*  0x03 | Payload size   | Fixed value (DATA_NUM:60)           */
+/*  0x04 | Data0 (MSBside)| Short type  (signed, big endian)    */
+/*  ...  | ...            |                                     */
+/*  0x3F | Data29(LSBside)|                                     */
+/*        ----------------                                      */
+
+Ticker      sampling;           /* Interval timer for A/D sampling */
+AnalogIn    wave_in(p20);       /* A/D port */
+USBSerial   serial;
+FilterTest  filter;
+
+DigitalIn   hpf_on(p28);        /* Hiph pass filter */
+DigitalIn   lpf_on(p27);        /* Low pass filter */
+DigitalIn   brf_on(p26);        /* Notch (Band reject) filter */
+/*  [ DIP switch ]                                  */
+/*    TG-LPC11U35-501         +3.3V                 */
+/*  | CN1         CN2 |        ---                  */
+/*  |     mbed BD     |         |                   */
+/*  |              13 | p28 -/ -+  Hiph pass filter */
+/*  |              14 | p27 -/ -+  Low pass filter  */
+/*  |              15 | p26 -/ -+  Notch filter     */
+/*  |                 |                             */
+/*  pull-down is default as below.                  */
+/*  http://developer.mbed.org/handbook/DigitalIn    */
+/*  It says "By default, the DigitalIn is setup     */
+/*          with an internal pull-down resistor."   */
+/*  Better to set the pins to pull-up mode and the  */
+/*  switch connected to GND.                        */
+
+DigitalOut  dbg_pin1(p21);      /* for debug */
+DigitalOut  dbg_pin2(p22);      /* for debug */
+DigitalOut  dbg_led1(LED1);     /* for debug */
+DigitalOut  dbg_led2(LED2);     /* for debug */
+
+int32_t idx, toggle, send_flag;
+uint8_t cntr;
+uint8_t buf[BUF_NUM][PACKET_SIZE];
+
+
+/** Initialize buffer
+ *  @param      tgl    buffer toggle index
+ *  @param      ctr    packet counter
+ */
+void init_buf(int32_t tgl, uint8_t ctr)
+{
+    int i;
+    if(tgl>BUF_NUM) {
+        return;
+    }
+    buf[tgl][0] = PACKET_HEADER;
+    buf[tgl][1] = WAVEFORM_ID;
+    buf[tgl][2] = ctr;              /* Packet counter */
+    buf[tgl][3] = DATA_NUM;         /* Payload size */
+    idx = 4;                        /* Start index of waveform */
+    for(i=4; i<PACKET_SIZE; i++) {  /* Initialize array just in case */
+        buf[tgl][i] = 0;
+    }
+}
+
+/** Interval timer for read A/D value
+ */
+void ad_sampling()
+{
+    int32_t wav_temp;
+    dbg_pin1 = ON;      /* Calculation time for filter for debug */
+    dbg_led1 = hpf_on;  /* High pass filter enable status for debug */
+    dbg_led2 = lpf_on;  /* Low pass filter enable status for debug */
+
+    /* Read and filter data */
+    wav_temp = (int32_t)filter.calc( (double)(wave_in.read_u16() - INT16_MAX), hpf_on, lpf_on, brf_on );
+    wav_temp = (wav_temp > INT16_MAX) ? INT16_MAX : wav_temp;   /* Clip ceiling */
+    wav_temp = (wav_temp < INT16_MIN) ? INT16_MIN : wav_temp;   /* Clip floor */
+    buf[toggle][idx] = (uint8_t)((wav_temp >> 8 ) & BYTE_MASK); /* MSB side (big endian) */
+    idx++;
+    buf[toggle][idx] = (uint8_t)(wav_temp & BYTE_MASK);         /* LSB side */
+    idx++;
+
+    dbg_pin1 = OFF; /* for debug */
+
+    /* Switch buffer */
+    if(idx >= PACKET_SIZE) {    /* Counter reached */
+        toggle = !toggle;
+        cntr = (cntr + 1 ) % CNTR_SIZE;
+        init_buf(toggle, cntr);
+        send_flag = ON;          /* Set flag */
+    }
+}
+
+/** Send data packet
+ *  @param      p_buf   Data array
+ *  @param      size    Data length
+ */
+bool send_packet(uint8_t *p_buf, uint16_t size)
+{
+    if(serial.writeable()) {
+        dbg_pin2 = ON;   /* for debug */
+        serial.writeBlock (p_buf, size);    /* Send data via USB */
+        dbg_pin2 = OFF;  /* for debug */
+        return true;
+    } else {
+        return false;
+    }
+}
+
+/** Main function
+ */
+int main()
+{
+    /* Initialization */
+    idx = 0;
+    toggle = 0;
+    cntr = 0;
+    send_flag = 0;
+    init_buf(toggle, cntr);
+    init_buf(!toggle, cntr);
+
+    dbg_pin1 = OFF;
+    dbg_pin2 = OFF;
+    dbg_led1 = LED_OFF;
+    dbg_led2 = LED_OFF;
+
+    /* Start interval timer */
+    sampling.attach(&ad_sampling, SAMPLING_RATE);
+
+    /* Main loop */
+    while(1) {
+        if(send_flag != OFF) {
+            /* Send data */
+            send_packet(buf[!toggle], (uint16_t)PACKET_SIZE);
+
+            /* Disable interrupt */
+            __disable_irq();
+            send_flag = OFF;    /* Clear flag */
+            __enable_irq();
+        }
+    }
+}