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)
Committer:
t_tatsuoka
Date:
Thu Jul 30 10:23:54 2015 +0000
Revision:
2:c9471599e9eb
Parent:
1:4172c4324c2d
Notch filter 60 Hz version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
t_tatsuoka 0:7a4d80e7ea81 1 /**
t_tatsuoka 0:7a4d80e7ea81 2 * @file Main.cpp
t_tatsuoka 0:7a4d80e7ea81 3 * @brief Send 1ch waveform data to PC via USB serial
t_tatsuoka 0:7a4d80e7ea81 4 * @date 2015.02.22
t_tatsuoka 1:4172c4324c2d 5 * @version 1.0.2
t_tatsuoka 0:7a4d80e7ea81 6 */
t_tatsuoka 0:7a4d80e7ea81 7 #include "mbed.h"
t_tatsuoka 0:7a4d80e7ea81 8 #include "USBSerial.h"
t_tatsuoka 0:7a4d80e7ea81 9 #include "FilterTest.h"
t_tatsuoka 0:7a4d80e7ea81 10
t_tatsuoka 0:7a4d80e7ea81 11 #define ON (1)
t_tatsuoka 0:7a4d80e7ea81 12 #define OFF (0)
t_tatsuoka 0:7a4d80e7ea81 13
t_tatsuoka 0:7a4d80e7ea81 14 #define LED_ON (0)
t_tatsuoka 0:7a4d80e7ea81 15 #define LED_OFF (1)
t_tatsuoka 0:7a4d80e7ea81 16
t_tatsuoka 0:7a4d80e7ea81 17 #define BYTE_MASK (0xFF)
t_tatsuoka 0:7a4d80e7ea81 18 #define INT16_MAX (32767)
t_tatsuoka 0:7a4d80e7ea81 19 #define INT16_MIN (-32768)
t_tatsuoka 0:7a4d80e7ea81 20
t_tatsuoka 0:7a4d80e7ea81 21 #define SAMPLING_RATE (0.001) /* A/D sampling rate (1ms) */
t_tatsuoka 0:7a4d80e7ea81 22
t_tatsuoka 0:7a4d80e7ea81 23 #define PACKET_HEADER (0xAA)
t_tatsuoka 0:7a4d80e7ea81 24 #define WAVEFORM_ID (0x01)
t_tatsuoka 1:4172c4324c2d 25 #define PACKET_SIZE (34)
t_tatsuoka 1:4172c4324c2d 26 #define DATA_NUM (30)
t_tatsuoka 0:7a4d80e7ea81 27 #define BUF_NUM (2)
t_tatsuoka 0:7a4d80e7ea81 28 #define CNTR_SIZE (100)
t_tatsuoka 0:7a4d80e7ea81 29 /* [ Packet format ] */
t_tatsuoka 0:7a4d80e7ea81 30 /* ---------------- */
t_tatsuoka 0:7a4d80e7ea81 31 /* 0x00 | Header byte | Fixed value (PACKET_HEADER:0xAA) */
t_tatsuoka 0:7a4d80e7ea81 32 /* 0x01 | Data type | ID value (0x01:Waveform) */
t_tatsuoka 0:7a4d80e7ea81 33 /* 0x02 | Packet counter | Count value (0to99 < CNTR_SIZE:100) */
t_tatsuoka 1:4172c4324c2d 34 /* 0x03 | Payload size | Fixed value (DATA_NUM:30) */
t_tatsuoka 0:7a4d80e7ea81 35 /* 0x04 | Data0 (MSBside)| Short type (signed, big endian) */
t_tatsuoka 0:7a4d80e7ea81 36 /* ... | ... | */
t_tatsuoka 1:4172c4324c2d 37 /* 0x21 | Data29(LSBside)| */
t_tatsuoka 0:7a4d80e7ea81 38 /* ---------------- */
t_tatsuoka 0:7a4d80e7ea81 39
t_tatsuoka 0:7a4d80e7ea81 40 Ticker sampling; /* Interval timer for A/D sampling */
t_tatsuoka 0:7a4d80e7ea81 41 AnalogIn wave_in(p20); /* A/D port */
t_tatsuoka 0:7a4d80e7ea81 42 USBSerial serial;
t_tatsuoka 0:7a4d80e7ea81 43 FilterTest filter;
t_tatsuoka 0:7a4d80e7ea81 44
t_tatsuoka 0:7a4d80e7ea81 45 DigitalIn hpf_on(p28); /* Hiph pass filter */
t_tatsuoka 0:7a4d80e7ea81 46 DigitalIn lpf_on(p27); /* Low pass filter */
t_tatsuoka 0:7a4d80e7ea81 47 DigitalIn brf_on(p26); /* Notch (Band reject) filter */
t_tatsuoka 0:7a4d80e7ea81 48 /* [ DIP switch ] */
t_tatsuoka 0:7a4d80e7ea81 49 /* TG-LPC11U35-501 +3.3V */
t_tatsuoka 0:7a4d80e7ea81 50 /* | CN1 CN2 | --- */
t_tatsuoka 0:7a4d80e7ea81 51 /* | mbed BD | | */
t_tatsuoka 0:7a4d80e7ea81 52 /* | 13 | p28 -/ -+ Hiph pass filter */
t_tatsuoka 0:7a4d80e7ea81 53 /* | 14 | p27 -/ -+ Low pass filter */
t_tatsuoka 0:7a4d80e7ea81 54 /* | 15 | p26 -/ -+ Notch filter */
t_tatsuoka 0:7a4d80e7ea81 55 /* | | */
t_tatsuoka 0:7a4d80e7ea81 56 /* pull-down is default as below. */
t_tatsuoka 0:7a4d80e7ea81 57 /* http://developer.mbed.org/handbook/DigitalIn */
t_tatsuoka 0:7a4d80e7ea81 58 /* It says "By default, the DigitalIn is setup */
t_tatsuoka 0:7a4d80e7ea81 59 /* with an internal pull-down resistor." */
t_tatsuoka 0:7a4d80e7ea81 60 /* Better to set the pins to pull-up mode and the */
t_tatsuoka 0:7a4d80e7ea81 61 /* switch connected to GND. */
t_tatsuoka 0:7a4d80e7ea81 62
t_tatsuoka 0:7a4d80e7ea81 63 DigitalOut dbg_pin1(p21); /* for debug */
t_tatsuoka 0:7a4d80e7ea81 64 DigitalOut dbg_pin2(p22); /* for debug */
t_tatsuoka 0:7a4d80e7ea81 65 DigitalOut dbg_led1(LED1); /* for debug */
t_tatsuoka 0:7a4d80e7ea81 66 DigitalOut dbg_led2(LED2); /* for debug */
t_tatsuoka 0:7a4d80e7ea81 67
t_tatsuoka 0:7a4d80e7ea81 68 int32_t idx, toggle, send_flag;
t_tatsuoka 0:7a4d80e7ea81 69 uint8_t cntr;
t_tatsuoka 0:7a4d80e7ea81 70 uint8_t buf[BUF_NUM][PACKET_SIZE];
t_tatsuoka 0:7a4d80e7ea81 71
t_tatsuoka 0:7a4d80e7ea81 72
t_tatsuoka 0:7a4d80e7ea81 73 /** Initialize buffer
t_tatsuoka 0:7a4d80e7ea81 74 * @param tgl buffer toggle index
t_tatsuoka 0:7a4d80e7ea81 75 * @param ctr packet counter
t_tatsuoka 0:7a4d80e7ea81 76 */
t_tatsuoka 0:7a4d80e7ea81 77 void init_buf(int32_t tgl, uint8_t ctr)
t_tatsuoka 0:7a4d80e7ea81 78 {
t_tatsuoka 0:7a4d80e7ea81 79 int i;
t_tatsuoka 0:7a4d80e7ea81 80 if(tgl>BUF_NUM) {
t_tatsuoka 0:7a4d80e7ea81 81 return;
t_tatsuoka 0:7a4d80e7ea81 82 }
t_tatsuoka 0:7a4d80e7ea81 83 buf[tgl][0] = PACKET_HEADER;
t_tatsuoka 0:7a4d80e7ea81 84 buf[tgl][1] = WAVEFORM_ID;
t_tatsuoka 0:7a4d80e7ea81 85 buf[tgl][2] = ctr; /* Packet counter */
t_tatsuoka 0:7a4d80e7ea81 86 buf[tgl][3] = DATA_NUM; /* Payload size */
t_tatsuoka 0:7a4d80e7ea81 87 idx = 4; /* Start index of waveform */
t_tatsuoka 0:7a4d80e7ea81 88 for(i=4; i<PACKET_SIZE; i++) { /* Initialize array just in case */
t_tatsuoka 0:7a4d80e7ea81 89 buf[tgl][i] = 0;
t_tatsuoka 0:7a4d80e7ea81 90 }
t_tatsuoka 0:7a4d80e7ea81 91 }
t_tatsuoka 0:7a4d80e7ea81 92
t_tatsuoka 0:7a4d80e7ea81 93 /** Interval timer for read A/D value
t_tatsuoka 0:7a4d80e7ea81 94 */
t_tatsuoka 0:7a4d80e7ea81 95 void ad_sampling()
t_tatsuoka 0:7a4d80e7ea81 96 {
t_tatsuoka 0:7a4d80e7ea81 97 int32_t wav_temp;
t_tatsuoka 0:7a4d80e7ea81 98 dbg_pin1 = ON; /* Calculation time for filter for debug */
t_tatsuoka 0:7a4d80e7ea81 99 dbg_led1 = hpf_on; /* High pass filter enable status for debug */
t_tatsuoka 0:7a4d80e7ea81 100 dbg_led2 = lpf_on; /* Low pass filter enable status for debug */
t_tatsuoka 0:7a4d80e7ea81 101
t_tatsuoka 0:7a4d80e7ea81 102 /* Read and filter data */
t_tatsuoka 0:7a4d80e7ea81 103 wav_temp = (int32_t)filter.calc( (double)(wave_in.read_u16() - INT16_MAX), hpf_on, lpf_on, brf_on );
t_tatsuoka 0:7a4d80e7ea81 104 wav_temp = (wav_temp > INT16_MAX) ? INT16_MAX : wav_temp; /* Clip ceiling */
t_tatsuoka 0:7a4d80e7ea81 105 wav_temp = (wav_temp < INT16_MIN) ? INT16_MIN : wav_temp; /* Clip floor */
t_tatsuoka 0:7a4d80e7ea81 106 buf[toggle][idx] = (uint8_t)((wav_temp >> 8 ) & BYTE_MASK); /* MSB side (big endian) */
t_tatsuoka 0:7a4d80e7ea81 107 idx++;
t_tatsuoka 0:7a4d80e7ea81 108 buf[toggle][idx] = (uint8_t)(wav_temp & BYTE_MASK); /* LSB side */
t_tatsuoka 0:7a4d80e7ea81 109 idx++;
t_tatsuoka 0:7a4d80e7ea81 110
t_tatsuoka 0:7a4d80e7ea81 111 dbg_pin1 = OFF; /* for debug */
t_tatsuoka 0:7a4d80e7ea81 112
t_tatsuoka 0:7a4d80e7ea81 113 /* Switch buffer */
t_tatsuoka 0:7a4d80e7ea81 114 if(idx >= PACKET_SIZE) { /* Counter reached */
t_tatsuoka 0:7a4d80e7ea81 115 toggle = !toggle;
t_tatsuoka 0:7a4d80e7ea81 116 cntr = (cntr + 1 ) % CNTR_SIZE;
t_tatsuoka 0:7a4d80e7ea81 117 init_buf(toggle, cntr);
t_tatsuoka 0:7a4d80e7ea81 118 send_flag = ON; /* Set flag */
t_tatsuoka 0:7a4d80e7ea81 119 }
t_tatsuoka 0:7a4d80e7ea81 120 }
t_tatsuoka 0:7a4d80e7ea81 121
t_tatsuoka 0:7a4d80e7ea81 122 /** Send data packet
t_tatsuoka 0:7a4d80e7ea81 123 * @param p_buf Data array
t_tatsuoka 0:7a4d80e7ea81 124 * @param size Data length
t_tatsuoka 0:7a4d80e7ea81 125 */
t_tatsuoka 0:7a4d80e7ea81 126 bool send_packet(uint8_t *p_buf, uint16_t size)
t_tatsuoka 0:7a4d80e7ea81 127 {
t_tatsuoka 0:7a4d80e7ea81 128 if(serial.writeable()) {
t_tatsuoka 0:7a4d80e7ea81 129 dbg_pin2 = ON; /* for debug */
t_tatsuoka 0:7a4d80e7ea81 130 serial.writeBlock (p_buf, size); /* Send data via USB */
t_tatsuoka 0:7a4d80e7ea81 131 dbg_pin2 = OFF; /* for debug */
t_tatsuoka 0:7a4d80e7ea81 132 return true;
t_tatsuoka 0:7a4d80e7ea81 133 } else {
t_tatsuoka 0:7a4d80e7ea81 134 return false;
t_tatsuoka 0:7a4d80e7ea81 135 }
t_tatsuoka 0:7a4d80e7ea81 136 }
t_tatsuoka 0:7a4d80e7ea81 137
t_tatsuoka 0:7a4d80e7ea81 138 /** Main function
t_tatsuoka 0:7a4d80e7ea81 139 */
t_tatsuoka 0:7a4d80e7ea81 140 int main()
t_tatsuoka 0:7a4d80e7ea81 141 {
t_tatsuoka 0:7a4d80e7ea81 142 /* Initialization */
t_tatsuoka 0:7a4d80e7ea81 143 idx = 0;
t_tatsuoka 0:7a4d80e7ea81 144 toggle = 0;
t_tatsuoka 0:7a4d80e7ea81 145 cntr = 0;
t_tatsuoka 0:7a4d80e7ea81 146 send_flag = 0;
t_tatsuoka 0:7a4d80e7ea81 147 init_buf(toggle, cntr);
t_tatsuoka 0:7a4d80e7ea81 148 init_buf(!toggle, cntr);
t_tatsuoka 0:7a4d80e7ea81 149
t_tatsuoka 0:7a4d80e7ea81 150 dbg_pin1 = OFF;
t_tatsuoka 0:7a4d80e7ea81 151 dbg_pin2 = OFF;
t_tatsuoka 0:7a4d80e7ea81 152 dbg_led1 = LED_OFF;
t_tatsuoka 0:7a4d80e7ea81 153 dbg_led2 = LED_OFF;
t_tatsuoka 0:7a4d80e7ea81 154
t_tatsuoka 0:7a4d80e7ea81 155 /* Start interval timer */
t_tatsuoka 0:7a4d80e7ea81 156 sampling.attach(&ad_sampling, SAMPLING_RATE);
t_tatsuoka 0:7a4d80e7ea81 157
t_tatsuoka 0:7a4d80e7ea81 158 /* Main loop */
t_tatsuoka 0:7a4d80e7ea81 159 while(1) {
t_tatsuoka 0:7a4d80e7ea81 160 if(send_flag != OFF) {
t_tatsuoka 0:7a4d80e7ea81 161 /* Send data */
t_tatsuoka 0:7a4d80e7ea81 162 send_packet(buf[!toggle], (uint16_t)PACKET_SIZE);
t_tatsuoka 0:7a4d80e7ea81 163
t_tatsuoka 0:7a4d80e7ea81 164 /* Disable interrupt */
t_tatsuoka 0:7a4d80e7ea81 165 __disable_irq();
t_tatsuoka 0:7a4d80e7ea81 166 send_flag = OFF; /* Clear flag */
t_tatsuoka 0:7a4d80e7ea81 167 __enable_irq();
t_tatsuoka 0:7a4d80e7ea81 168 }
t_tatsuoka 0:7a4d80e7ea81 169 }
t_tatsuoka 0:7a4d80e7ea81 170 }