UMEHOSHI ITA TOP PAGE

[Raspberry Pi 3 Model A+]と[UMEHOSHI ITA]を乗せたモータ付き台車を使った実験

このページで示したロボットの倒立振子の検討の記録の続きのページです。
なお、EEPROMの内容は、このページで作成した内容を使っている。

ロボットの倒立振子の検討の記録 その3B

ここで使用するロボットは二輪車と、別途の一つの支柱が接地する構造で、電源を切っても倒れない構造になっている。
この状態から、支柱浮かせて二輪だけで動かす目標の検討です。

この 動作動画(Xのリンク) で示したように振動を止めることができませんでした。
この制御では6種類のPWM値に変更するためのエントリーポイントをUMEHOSHI ITA基板内に用意して、それをUSB利用の呼び出しで変更していました。
USBではレイテンシ(Latency:データの往復にかかる遅延時間(遅さ))や、ジッタ(Jitter:通信中にその遅延時間が変動する揺らぎ(ばらつき))が 大きいので、モーターのPWM制御には向かないということです。
このような場合、 この問題を回避するため、PWMの制御にUSBを使わずに別回線でコントロールします。
SPI(Serial Peripheral Interface:4本の信号線「SCLK, MOSI, MISO, CS」を使用した数Mbps?数10Mbpsの高速通信が可能な全二重同期シリアル通信規格)の 使用を試みることにした。
SPIは、送信と受信が同時に行われる通信方式です。
クロック1回で、Masterからの1bit送信と、Slaveからの 1bit送信を 同時に起きます。
送信だけや、受信だけという動作は基本的にできません。
ですが送信だけに見えるケースとして、Slaveが何もデータを出さない場合があります。
SPIでは、受信だけはできません。なぜならクロックは Masterが送信するときにしか発生しないからです。
そのため受信だけしたい場合、ダミーデータを送信する必要があります。
SPIでの Master / Slave の違い
項目MasterSlave
クロック 生成する(出力端子) 受け取る(受信端子)
CS制御 制御する(出力端子) 選択される(受信端子)
通信開始 できる できない
通信速度 決定する 従う
MOSI(Master Out Slave In) 送信 受信
MISO(Master In Slave Out) 受信 送信
Raspberry Pi 3 Model A+をマスターとして使います。まずはその通信の確認から始めています。

Raspberry Pi 3 Model A+と「UMEHOSHI ITA」をSPIで通信するためのハード追加

まず、「UMEHOSHI ITA」側ですがCN10のコネクタを介した接続を試みます。
このコネクタはデフォルトでUART1の通信を行うために用意されているのですが、PIC32のペリフェラルピンセレクト (PPS: Peripheral Pin Select)で 用途をSPI用に変更して使う訳です。次のようにすればSPI通信(スレーブ)として使えると試みました。
PIC32MX270の18,12,26,17番ピンをPPSで、SS2,SDI2,SCLK2,SDO2に変更してSPI通信(スレーブ)にして、マスター側をRaspberry Piとして使います。
CN10
端子番号
PIC32MXの端子番号変更前のUART1変更後のSPI(スレーブ)拡張基板内
コネクタ番号
Raspberry ピン番号とSPI端子(マスター)
118 RB9RTS(出力)RB9を SS2 イネーブル入力端子にPPSで変更1Pin24 GPIO8 (CE0)
228  Vcc(3.3v)Vcc(3.3v)
327  GNDGND2GND
412 RA4RX(入力)RA4をSDI2(入力)にPPSで変更3Pin19 GPIO10 (MOSI)
511 RB4
TX(出力)
RB4を単なる入力端子に変更
SCLK2 (PIC32のRB15をPPSで変更した26番ピンにジャンパー接続
4Pin23 GPIO11 (SCLK)
617 RB8CTS(入力) RB8をSDO2(出力)にPPSで変更 5Pin21 GPIO9 (MISO)
既存のUART用コネクタを経由させていますが、PIC32MX270F256B-50I/SPのSPI2用クロックの「26番ピン (RB15)」はコネクタCN-10のピン5にジャンパー接続する。

[Raspberry Pi 3 Model A+]と[UMEHOSHI ITA]を乗せたモータ付き台車で、
拡張ボードでSPI用のコネクタを追加した回路結線図&配置図

Raspberry Pi 3 Model A+側のSPIマスターで通信するための動作確認コード

まず、SPIが有効化されているか確認し、そうでなければ次のように有効します。
sudo raspi-config
Interface Options → SPI → Enable
そして、次のコマンドで
suzuki@raspberrypi:~ $ ls /dev/spidev*
/dev/spidev0.0  /dev/spidev0.1
suzuki@raspberrypi:~ $
suzuki@raspberrypi:~ $ lsmod | grep spi
spidev                 20480  0
spi_bcm2835            20480  0
suzuki@raspberrypi:~ $
/dev/spidev0.0と /dev/spidev0.1は、それぞれが SPIバス0のCE0がGPIO8(Pin24)で使えることと、CE1のGPIO7(Pin26)が使えることを示している。
lsmod は Linuxで現在ロードされているカーネルモジュール(デバイスドライバ)を表示するコマンドで、これでspi関連ドライバがあるか確認している。

以下は、
RaspberryPi3のPin24 GPIO8 (CE0)、Pin19 GPIO10 (MOSI)、Pin21 GPIO9 (MISO)、Pin23 GPIO11 (SCLK)として利用し、 SPIマスターの動作で、Enterですしずつ確認しながら送でするのシンプルなpythonコードです。
import spidev
import time

spi = spidev.SpiDev() # SPI操作オブジェクト生成
spi.open(0, 0)        # bus=0 device=0 (CE0) でSPIオープン

spi.max_speed_hz = 7812500 # 7.8 MHzSPIクロック
spi.mode = 0 # クロック信号(SCLK)はLow待機、LowからHighに立ち上がる瞬間でデータを読み取り

v=0 # 送信データ(0,1,2・・・・と増やした値を Enterキー操作で少しずつ送る)
while True:
   send_data = [v] #  例えばビッグエンディアンで0x15AFを送るなら[0x15, 0xAF]のリストで送る。決まってないが一般の受信側のオーダーで送る。
   input("Enter>") # Enterで送信へ進む
   print("Send :", send_data)
   recv_data = spi.xfer2(send_data)# 送受信
   # print("Send :", send_data) # (send_dataの内容は、受信データ置き換わる挙動もある)
   print("Recv :", recv_data) 
   time.sleep(0.1)
   v += 1 # 送信データの後進



Raspberry Pi 3 Model A+と「UMEHOSHI ITA」をSPIで通信する

PIC32MX270側のSPIスレーブ確認コード(ポーリング版)

前述のRaspberry Pi 3のPythonのSPIマスターコードに対するPIC32MX270側のSPIスレーブ用のポーリング用コードです。
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include <proc/p32mx270f256b.h>
#include <sys/attribs.h>//割込み関係の定義

int spi_out_v = 0x0ff; // SPI出力用データ

/*
 PIC32MX270F256B-50I/SP (SP は 28pin SPDIP パッケージ)のUART1を、
 18番ピンをRTS(出力)、12ピンをRX(入力)、11ピンをTX(出力)、17ピンRB8をCTS(入力)
 として使っているが、 これを、次のSPI2のスレーブモードに設定し直す
 18番ピンをCS GPIO入力、12ピンをSDI2(入力)、11ピンRB5をSDO2(出力)、17ピンをデジタル入力
 そのためのPPSは「ピン配線設定」関数。つまり **「配線設定」**です。
 */
void PPS_Init_SPI2_Slave(void)
{   
    /* ---------- UART1のフロー制御(CTS/RTS)を解除 ---------- */
    U1MODEbits.UEN = 0b00;  // UART1はTX/RXのみ使用(CTS/RTSピンを開放)
    U1MODEbits.ON = 0;      // UART1自体を使わない場合は停止

    ODCBbits.ODCB9 = 0; // RB9デフォルト設定のオープンドレイン無効
    CNPUBbits.CNPUB9 = 0;//CNPUB (Change Notice Pull-up B) レジスタの第9ビットを0
    //(これにより、RB9ピンの内部プルアップ抵抗を無効)
    CNPDBbits.CNPDB9 = 0;//CNPDB (Change Notice Pull-down B)レジスタの第9ビットを 0
    //(これにより、RB9ピンの内部プルダウン抵抗を無効) 
    LATBbits.LATB9 = 1; // RB9のRTS(出力)をHiにする
    TRISBbits.TRISB9 = 1;// RB9を入力ピンにする (基板のパターンが繋がっているため)
    
    LATBbits.LATB4 = 1;  // RB4を1にする。(必要ないかも?)
    TRISBbits.TRISB4 = 1; // RB4を入力用に指定
    ODCBbits.ODCB4 = 0; // デフォルト設定のオープンドレイン無効
    CNPUBbits.CNPUB4 = 0;//内部プルアップ抵抗を無効
    CNPDBbits.CNPDB4 = 0;//内部プルダウン抵抗を無効

    TRISAbits.TRISA4 = 1;   // RA4  (pin12) SDI2入力へ
    ANSELBbits.ANSB15 = 0;  // 26番ピンのRB15をデジタルモードに設定
    TRISBbits.TRISB15 = 1;  // スレーブの場合は入力、マスターなら0(出力)に設定

    TRISBbits.TRISB8 = 0; // RB8を出力用に指定
    CNPUBbits.CNPUB8 = 0;//内部プルアップ抵抗を無効

    /* ---------- PPS設定アンロック ---------- */
    SYSKEY = 0xAA996655;        // 書き込み保護解除キー1
    SYSKEY = 0x556699AA;        // 書き込み保護解除キー2
    CFGCONbits.IOLOCK = 0;      // PPSレジスタのロック解除

    /* ---------- 入力PPS設定 ---------- */
    SS2R  = 0b0100;             // SS2入力をRB9へ
    SDI2R = 0b0010;             // SDI2入力をRA4へ

    /* ---------- 出力PPS設定 ---------- */
    RPB8R = 0b0100; // SDO2へ
    asm("NOP");

    /* ---------- PPS再ロック ---------- */
    CFGCONbits.IOLOCK = 1;
    SYSKEY = 0;                 // 保護再有効
}

/*
 SPI2に関する周辺機能設定の初期設定
 * クロック極性、スレーブ設定、割り込みなど、ここだけ変更する可能性を考慮して
 * 「ピン配線設定」のPPS_Init_SPI2_Slaveを別関数にしている。 
 */
void Init_SPI2_Slave(void)
{
    _RB5 = 1; // D1 LED の初期点灯設定

    PPS_Init_SPI2_Slave(); // PIC32MX270F256B-50I/SP のSPI2スレーブ用端子にピン割り当てを変更

    SPI2CON = 0;                // SPI2制御レジスタ初期化
    SPI2STAT = 0;               // ステータス初期化

    /* ---------- SPIモード設定 ---------- */
    SPI2CONbits.MSTEN = 0;      // 0 = スレーブモード
    SPI2CONbits.SSEN  = 1;      // SS有効 Slave Select Enable (Slave mode) bit
    SPI2CONbits.MODE16 = 0;     // 8bit通信
    SPI2CONbits.MODE32 = 0;     // 32bit通信無効

    /* SPIモード0設定 (多くのマスターが使用) */
    SPI2CONbits.CKP = 0;        // クロックアイドルLow
    SPI2CONbits.CKE = 1;        // クロック立上りでデータ更新

    SPI2CONbits.SMP = 0;        // スレーブでは通常0

    SPI2BUF;                    // バッファをダミー読み出し
    SPI2STATbits.SPIROV = 0;    // 受信オーバーフロークリア

    // SPI用Enhanced Buffer(ENHBUF)を0(デフォルト)に指定(重要)
    SPI2CONbits.ENHBUF = 0;
    SPI2CONbits.SRXISEL = 1; //01受信バッファが1byteに指定
   
    SPI2CONbits.ON = 1;         // SPI2モジュール有効
    SPI2BUF = spi_out_v;// 最初の送信データのセット(重要)
}


void timer4() // SPIスレーブ のポーリング処理の確認用タイマー処理
{
	static int count  = 0;
	if(++count  % 1000 != 0) return;
	// count  が 1000の倍数時だけ(0.5秒ごと)に以下を実行
	
	_RB5 = ! _RB5;// このタイマーの動作確認用の D1 LED 点滅の出力を反転

	if (SPI2STATbits.SPIRBF == 1) { // SPI受信バッファが一杯になったら
		// ここを通るなら、SPI受信ができている(配線とSPI設定はOK)
		uint8_t rxData = SPI2BUF; // 受信データを読み出す(これでSPIRBFが0に戻る)
		_clear_beep_code();
		_debug_hex8(0, rxData , 1); // 受信データ確認
		spi_out_v-=1;
		while(SPI2STATbits.SPITBE == 0); // 送信バッファ空待ち
		SPI2BUF = spi_out_v;// 次の送信データのセット
	}
	if (SPI2STATbits.SPIROV == 1) { // エラーフラグが立っていないか
		SPI2STATbits.SPIROV = 0; // 一旦クリア
		_debug_hex16(0, SPI2BUF, 1);
	}
}

// UMEHOSHI ITA のRAMプログラムの設定希望プログラム(0x80005000番地より起動)
__attribute__((address( 0x80005000 ))) void start (void);
void start()
{
	_clear_beep_code(); // _debug_hex? 関数利用の初期化
	_UM_PTR_GOTO_BEEP = NULL; // debug_hex?の出力をループしない設定

	Init_SPI2_Slave();// SPI2の初期化

	// デフォルトで0.00005秒ごとに呼び出される関数に、SPIスレーブ のポーリング処理のtimer4を設定
	_HANDLES[_IDX_TIMER_4_FUNC] = timer4;
     	T4CONbits.ON = 1;// timer4割込みオン(SPIスレーブ のポーリングの起動)
	
 	_RB5 = 0; // D1 LED の消灯
	_debug_hex4(0,0x0f,1);//  _debug_hex? の動作確認用
	_send_string("start END\r\n");//起動関数終了の表示
}
上記はTimer4のインターバルタイマーの割り込みを使い、この繰り返しの中でSPIの受信を監視して、受信処理をする例です。

Raspberry Pi 3 Model A+と「UMEHOSHI ITA」をSPI割り込みで通信するためのソフト変更

PIC32MX270側のSPIスレーブ確認コード(割り込み版)

上記のTimer割り込みは使わずに、SPIの受信による割り込みです。
PIC32MX270側のSPI割り込み処理を作る場合、PIC32MX270側のfirmwareを追加、変更が必要になる。
今後の割り込み処理変更と、これまでの「UMEHOSHI ITA」基板利用コードに影響がないように、firmwareを変更する。
(このfirmware変更内容は、2026年5月移行に適用予定)
割り込み処理は、firmwareのコード(my_sys.c)に、次のコードを追加して実現している。
void __ISR(_SPI2_VECTOR, IPL3SOFT) SPI2_Handler(void)
{
    ((void (**)(void) )_PTR_HANDLERS)[_IDX_SPI2_FUNC]();
}
つまり、_PTR_HANDLERS)[_IDX_SPI2_FUNC]に、ユーザー作成の割り込み処理のポイントを記憶しておいて、それを実行させるコードです。
そのたために必要な次のマクロ定義を、common.hに追加しました。
#define _IDX_PPS_INIT_SPI2_SLAVE 70  // ★ SPI2のPPS 設定 PPS_Init_SPI2_Slave
#define _PPS_Init_SPI2_Slave()  (((void (**)(void) )_PTR_HANDLERS)[_IDX_PPS_INIT_SPI2_SLAVE]())
#define _IDX_INIT_SPI2_SLAVE 71 // ★ SPI2の初期設定 割り込みを含む初期化 Init_SPI2_Slave
#define _Init_SPI2_Slave()  (((void (**)(void) )_PTR_HANDLERS)[_IDX_INIT_SPI2_SLAVE]())
#define _IDX_SPI2_FUNC 72       // ★ SPI2割り込みで呼ぶ関数記憶用の添え字
そして、上記の_PTR_HANDLERS[_IDX_PPS_INIT_SPI2_SLAVE]に記憶する次のデフォルト関数を次のように定義しています。
(この記述用にmy_option.cのファイルを追加しました。 この「ピン配線設定」関数のvoid PPS_Init_SPI2_Slave(void)は、ポーリングで使った関数と同じです。)
/*
 PIC32MX270F256B-50I/SP (SP は 28pin SPDIP パッケージ)のUART1を、
 18番ピンをRTS(出力)、12ピンをRX(入力)、11ピンをTX(出力)、17ピンRB8をCTS(入力)
 として使っているが、 これを、次のSPI2のスレーブモードに設定し直す
 18番ピンをCS GPIO入力、12ピンをSDI2(入力)、11ピンRB5をSDO2(出力)、17ピンをデジタル入力
 そのためのPPSは「ピン配線設定」関数。つまり **「配線設定」**です。
 */
void PPS_Init_SPI2_Slave(void)
{   
    /* ---------- UART1のフロー制御(CTS/RTS)を解除 ---------- */
    U1MODEbits.UEN = 0b00;  // UART1はTX/RXのみ使用(CTS/RTSピンを開放)
    U1MODEbits.ON = 0;      // UART1自体を使わない場合は停止

    ODCBbits.ODCB9 = 0; // RB9デフォルト設定のオープンドレイン無効
    CNPUBbits.CNPUB9 = 0;//CNPUB (Change Notice Pull-up B) レジスタの第9ビットを0
    //(これにより、RB9ピンの内部プルアップ抵抗を無効)
    CNPDBbits.CNPDB9 = 0;//CNPDB (Change Notice Pull-down B)レジスタの第9ビットを 0
    //(これにより、RB9ピンの内部プルダウン抵抗を無効) 
    LATBbits.LATB9 = 1; // RB9のRTS(出力)をHiにする
    TRISBbits.TRISB9 = 1;// RB9を入力ピンにする (基板のパターンが繋がっているため)
    
    LATBbits.LATB4 = 1;  // RB4を1にする。(必要ないかも?)
    TRISBbits.TRISB4 = 1; // RB4を入力用に指定
    ODCBbits.ODCB4 = 0; // デフォルト設定のオープンドレイン無効
    CNPUBbits.CNPUB4 = 0;//内部プルアップ抵抗を無効
    CNPDBbits.CNPDB4 = 0;//内部プルダウン抵抗を無効

    TRISAbits.TRISA4 = 1;   // RA4  (pin12) SDI2入力へ
    ANSELBbits.ANSB15 = 0;  // 26番ピンのRB15をデジタルモードに設定
    TRISBbits.TRISB15 = 1;  // スレーブの場合は入力、マスターなら0(出力)に設定

    TRISBbits.TRISB8 = 0; // RB8を出力用に指定
    CNPUBbits.CNPUB8 = 0;//内部プルアップ抵抗を無効

    /* ---------- PPS設定アンロック ---------- */
    SYSKEY = 0xAA996655;        // 書き込み保護解除キー1
    SYSKEY = 0x556699AA;        // 書き込み保護解除キー2
    CFGCONbits.IOLOCK = 0;      // PPSレジスタのロック解除

    /* ---------- 入力PPS設定 ---------- */
    SS2R  = 0b0100;             // SS2入力をRB9へ
    SDI2R = 0b0010;             // SDI2入力をRA4へ

    /* ---------- 出力PPS設定 ---------- */
    RPB8R = 0b0100; // SDO2へ
    asm("NOP");

    /* ---------- PPS再ロック ---------- */
    CFGCONbits.IOLOCK = 1;
    SYSKEY = 0;                 // 保護再有効
}
同様で、my_option.cに_PTR_HANDLERS[__IDX_PPS_INIT_SPI2_SLAVE]に記憶する次のデフォルト関数を次のように定義しています。
/*
 SPI2に関する周辺機能設定の初期設定
 * クロック極性、スレーブ設定、割り込みなど、ここだけ変更する可能性を考慮して
 * 「ピン配線設定」のPPS_Init_SPI2_Slaveを別関数にしている。 
 */
void Init_SPI2_Slave(void)
{
    _RB5 = 1; // D1 LED の初期点灯設定

    PPS_Init_SPI2_Slave(); // PIC32MX270F256B-50I/SP のSPI2スレーブ用端子にピン割り当てを変更

    SPI2CON = 0;                // SPI2制御レジスタ初期化
    SPI2STAT = 0;               // ステータス初期化

    /* ---------- SPIモード設定 ---------- */
    SPI2CONbits.MSTEN = 0;      // 0 = スレーブモード
    SPI2CONbits.SSEN  = 1;      // SS有効 Slave Select Enable (Slave mode) bit
    SPI2CONbits.MODE16 = 0;     // 8bit通信
    SPI2CONbits.MODE32 = 0;     // 32bit通信無効

    /* SPIモード0設定 (多くのマスターが使用) */
    SPI2CONbits.CKP = 0;        // クロックアイドルLow
    SPI2CONbits.CKE = 1;        // クロック立上りでデータ更新

    SPI2CONbits.SMP = 0;        // スレーブでは通常0

    SPI2BUF;                    // バッファをダミー読み出し
    SPI2STATbits.SPIROV = 0;    // 受信オーバーフロークリア

    // SPI用Enhanced Buffer(ENHBUF)を0(デフォルト)に指定(重要)
    SPI2CONbits.ENHBUF = 0;
    SPI2CONbits.SRXISEL = 1; //01受信バッファが1byteに指定

    /* ---------- 割り込み設定 ---------- */
    IFS1bits.SPI2RXIF = 0;       // 受信割り込みフラグクリア
    IEC1bits.SPI2RXIE = 1;       // SPI2受信割り込み許可
    //IEC1bits.SPI2TXIE = 1;      // SPI2送信割り込み許可
    IEC1bits.SPI2EIE  = 1;      // SPI2エラー割り込み許可

    IPC9bits.SPI2IP = 3;  // 優先度(Priority)を 3 に設定 (1?7)
    IPC9bits.SPI2IS = 0;  // 副優先度(Sub-priority)を 0 に設定 (0?3)
   
    SPI2CONbits.ON = 1;         // SPI2モジュール有効
}
以上の関数定義は、my_sys.cのinit_handle_area関数内に、次のコード追加で行っています。
    extern void PPS_Init_SPI2_Slave(void);
    extern void Init_SPI2_Slave(void);
    extern void SPI2_Slave_func(void);
    handlers[_IDX_PPS_INIT_SPI2_SLAVE]=(void *)PPS_Init_SPI2_Slave; // SPI2利用のためのPPS設定
    handlers[_IDX_INIT_SPI2_SLAVE]=(void *)Init_SPI2_Slave; // SPI2の初期化デファルト関数登録
    handlers[_IDX_SPI2_FUNC]=(void *)SPI2_Slave_func;       // SPI2受信割り込みデファルト


以上を使ってumehoshiEdit.exeのツールで、 上述のRaspberryPi側のSPIマスターPythonプログラムからのSPIスレーブ受信をコードは次のようになりました。
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include <proc/p32mx270f256b.h>
#include <sys/attribs.h>//割込み関係の定義

int spi_out_v = 0x0ff; // SPI出力用データ

void SPI2_Slave_func(void)// スレーブ用割り込み処理から呼ばれる
{
    /* ---- 受信割り込み ---- */ 
    if (IFS1bits.SPI2RXIF)// SPI2RXIF = 受信バッファにデータが入った 
    {
        uint8_t data;
        data = SPI2BUF;        // SPI受信データを読む
                               // 読まないとSPIROV(オーバーフロー)が発生する
        /* ここで data を処理する */
        _clear_beep_code();
        _debug_hex8(0, data, 1); // 受信データ確認
        spi_out_v-=1;
        while(SPI2STATbits.SPITBE == 0); // 送信バッファ空待ち
        SPI2BUF = spi_out_v;// 次の送信データのセット
    }

    /* ---- エラー割り込み ---- */
    if (IFS1bits.SPI2EIF)
    {
        SPI2STATbits.SPIROV = 0;   // 受信オーバーフロー解除
        IFS1bits.SPI2EIF = 0;      // エラーフラグクリア
    }
}

// UMEHOSHI ITA のRAMプログラムの設定希望プログラム(0x80005000番地より起動)
__attribute__((address( 0x80005000 ))) void start (void);
void start()
{
	_clear_beep_code(); // _debug_hex? 関数利用の初期化
	_UM_PTR_GOTO_BEEP = NULL; // debug_hex?の出力をループしない設定

	_HANDLES[_IDX_SPI2_FUNC] = (void *)SPI2_Slave_func;// SPI割り込み関数の登録

	((void (**)(void) )_PTR_HANDLERS)[_IDX_INIT_SPI2_SLAVE]();// SPI2の初期化
	SPI2BUF = spi_out_v;// 最初の送信データのセット(重要)

	_RB5 = 0; // D1 LED の消灯
	_debug_hex4(0,0x0f,1);//  _debug_hex? の動作確認用
	_send_string("start END\r\n");//起動関数終了の表示
}