UMEHOSHI ITA TOP PAGE    COMPUTER SHIEN LAB

[UMEHOSHI ITA]の制御で使っているIC「PIC32MX270F256B-I/SO」のフラッシュメモリには、テスト用プログラムが書き込まれいています。
以降では、このプログラムを「テスト・ウメ・フラッシュ」と呼ぶことにして解説します。
また、「テスト・ウメ・フラッシュ」を利用したユーザー用のプログラムを 「ウメ・エディットプログラム」と呼ぶことにします。
「ウメ・エディットプログラム」の開発では「umehoshiEditツール」が必要で、 その取得や最初の操作情報は、こちらを参照してください。
(「PICKit3などの書き込みツール」をお持ちの方で、「テスト・ウメ・フラッシュ」を利用しないで、 「MPLAB X IDE」の開発環境ですべてをプログラミングする場合の情報ではありません。)
「テスト・ウメ・フラッシュ」をどのように利用して、「ウメ・エディットプログラム」を 作るかの解説で、「umehoshiEditツール」の使用例を示しています。
各サンプルは、このWebページ上でドラック&コピーして、貼り付けしてご利用ください。

各種確認プログラム左記に必要な部品の追加例

USBで接続されるホストにメッセージ(文字列)を送信する。

とくに必要ありません。
(D1のLEDは、あるとよい)

モータ制御、PWM (Timer2利用)

PWM対応の部品追加例

ADC(A/Dコンバータ)を使う(Timer3利用)

ADC 対応の部品追加例

BEEP(ブザー音で、デフォルトのCORE Timer、Timer1を利用)

BEEP SWITCH 対応の部品追加例

[UMEHOSHI ITA]単体で動作させる

Reset SW, Type-A, CN2 部品追加例

赤外線制御

U20,D4,D5,NPN, D3 部品追加例

UART を介して、Bluetoothで制御

CN11,CN-12 部品追加例

UART を介して、ESP32-WROOM-32DをBASIC制御

U19 部品追加例

UART を介して、RN4020(BLE)で制御

U17にRN4020の部品を追加する例

[UMEHOSHI ITA]のパルス変調で、圧電サンダーを鳴らす実験

[UMEHOSHI ITA]単体で動作させる時に必要な部品の追加です。

これは、こちらのリンク先に、このページに至る前の実験情報があります。


[UMEHOSHI ITA]のPORTB5の端子をON・OFFすることで、音を鳴らすことができます。
(PORTB5の端子の端子には、別途にLED D2のON・OFFも兼用しています。)

[UMEHOSHI ITA]のRAM領域のデータでパルス変調、圧電サンダーを鳴らす実験

下記ソースではTimer2 と連係させたOC2(Output Compare modules:出力コンペアモジュール)の割り込み利用して、change()でPWDの幅を変更しています。
(OC2により、PR2の値とTimer2のカウントが一致するまでPORTB5の出力を1にするPWDのハードを利用しています。)
なお「テスト・ウメ・フラッシュ」を利用したユーザー用のプログラム(ウメ・エディットプログラム)では、 _MEMO3(0x80009000番地)を先頭アドレスとする0x0F00byte(3840byte)記憶域があり、これをポインタ変数で管理します。
下記C言語ソースは、この記憶域を使って実験しています。(この記憶域はRAMなので、ROMのように消去の手続きが不要で実験向きです)
_MEMO3番地記憶の容量が少ないので、音の品質が多少悪くてもデータ量を抑える目標とし、4ビット(16段階)のデータでパルス変調としています。
_MEMO3の格納は、2つのデータを下位4ビットと上位4ビットの1バイト埋め込んで管理しています。

#include <xc.h> // pb5_pwd_c
#include "common.h"
int change_count = 0; // change()の割り込み回数計数で検証用 

#define NREP 6 // 1つ(4bit)のデータを、約(1/4410)秒周期で繰り返し使う回数(水平分解能指定パラメタ)

short int pwd_base[]={2, 62, 122, 182, 242, 303, 363, 423, 483, 543, 604, 664, 724, 784, 844, 905};
int idx_base=0;// 上記のPWDのデータテーブルのアクセス用添え字

char *pwd_datas=(char *)(0x80009000); // PWDのデータ添え字群の記憶領域の先頭アドレス
int pwd_size=0; // 上記ポインタから始まったデータのサイズ
int pwd_idx=0; // 上記アクセス用添え字
int pwd_count=0; // pwd_datasの各要素の上位、下位それぞれのデータを(NREP=6)回使い、(NREP+NREP)までのカウンタ

void change() // OC2割り込み関数 (PWMのデューティ サイクルの変更
{
	change_count++;//割り込み回数計測用 (約44100Hzの周期でカウント)
	if(pwd_count == 0){		// 下位4ビットの周期へ
		idx_base = pwd_datas[pwd_idx] & 0x0f;
		OC2RS = pwd_base[idx_base];
	}else if(pwd_count == NREP){	// 上位4ビットの周期へ
		idx_base = (pwd_datas[pwd_idx] >> 4) & 0x0f;
		OC2RS = pwd_base[idx_base];
	}
	if(++pwd_count == (NREP+NREP)){ //上位4ビットが終わって次の要素周期へ
		pwd_count=0;
		pwd_idx++;
		if( pwd_idx >= pwd_size ) {//周期要素を配列を使い終わった
			pwd_idx = 0;
			OC2RS=0;
			OC2CONbits.ON =0;	// OC2の動作OFF
		}
	}
	IFS0CLR = _IFS0_OC2IF_MASK;	// Clear the OC2 interrupt flag
}

void pb5_pwd(char *pwd_adr, int size)
{
	idx_base=0;			// PWDのデータテーブルのアクセス用添え字
	pwd_datas = pwd_adr;    // PWDのデータ記憶領域の先頭アドレス
	pwd_size = size;		// PWDのデータサイズ
	pwd_count = 0;		// PWDのデータアクセス用添え字

	// Timer2の初期化------------------
	T2CON =0x00000000;//typeB,16bit, [1:1]プリスケール これで(1/40e6)の周期で、TMR2をカウントアップ
	T2CONbits.TCKPS = 0;// 1:1プリスケール値
	TMR2=0x0000; //16bitタイマの設初期値(上記設定周期でカウントして、PR2と一致するとクリアして割り込み)
	PR2=906; //16bitタイマの設定値(周期設定用  =int((1/44100)/(1/40e6)-1)
	IEC0CLR = 0x00000200;//T2IE Timer2 desable(割込み不許可)

	// Output Compare module 2の初期化-(割り込み指定を含む)-----------------
	OC2CON = 0x0000;// Turn off OC2 while doing setup. 
	RPB5Rbits.RPB5R = 0x5; // RB5をOC2の出力にする。
	OC2CONbits.SIDL = 0; // アイドルモード中も動作を継続する
	OC2CONbits.OC32 = 0; //OC2R<15:0> およびOC2RS<15:0> を使って16 ビットタイマ源と比較する
	OC2CONbits.OCTSEL = 0; // Timer2 をこの出力コンペア モジュールのクロック源として使う
	OC2CONbits.OCM = 5; // OC2 をPWM モードにし、フォルトピンを無効にする

	_HANDLES[_IDX_OUTPUT_COMPARE_2_VECTOR] = change;// OC2割り込み関数を登録
	IFS0CLR = _IFS0_OC2IF_MASK;	// Clear the OC2 interrupt flag
	IEC0SET = _IEC0_OC2IE_MASK;	// Enable OC2 interrupt 
	IPC2bits.OC2IP = 7;// Set OC1 interrupt priority to 7
	IPC2bits.OC2IS = 3;// Set Subpriority to 3, maximum
	//OC2R = 0;//出力コンペア1 コンペアレジスタの初期値
	//OC2RS = 905;//出力コンペア1 セカンダリコンペアレジスタ(デューティー比設定用で上記設定の最大値 )

	T2CONbits.ON = 1; // Timer2の動作スタート
	OC2CONbits.ON =1;	// OC2の動作スタート
}

__attribute__((address( 0x80005000 ))) void main(void);
void main()
{
	PORTBINV = 0x8000;	// LED1を反転
	change_count = 0;		// 検証用
	unsigned long count_now = _CP0_GET_COUNT();//(1/40e6)*2 =50ナノ秒でカウントするコアタイマーの値を取得
	unsigned long count_end = count_now  + 200000000;//の追加が10秒後のカウント値(10/50e-9=200000000)

	pb5_pwd((char *) 0x80009000, 3451);// 指定番地(_MEMO3)より指定サイズデータを鳴らす

	while(count_now < count_end && OC2CONbits.ON == 1){ // 10秒間、または再生中の実行
		count_now = _CP0_GET_COUNT();//50ナノでカウントするコアタイマーの値を取得
	}
	PORTBINV = 0x8000;// LED1を反転

	_send_decimal(change_count,10);
	_send_string(" <==change_count\r\n");
}

上記のpb5_pwd関数で使うデータ群を生成するpythonのコード

上記pb5_pwd((char *) 0x80009000, 3451);の実行は、0x80009000のアドレスに、 3451バイトのPDWデータ群を必要とします。
それを設定するための「UME専用Hexコマンド」ファイルを生成するプログラム例が コードです。
コード内で、WAV_FILE_PATHに鳴るサウンドのWAVファイル、
starting_addressにpb5_pwdの第1引数で設定するPDWデータ群のアドレス、
pathに生成する「UME専用Hexコマンド」ファイルパスを設定して実行します。
# wav_to_UME.py 『wavファイルからパルス変調用ファイルを作成する』
import wave
# 参考https://docs.python.org/ja/3/library/wave.html
import numpy as np
import matplotlib.pyplot as plt
from circuit import integral_circuit, differentiator,getTestSingnal

WAV_FILE_PATH="え_何.wav"# 変換対象のこの音声が記憶されるサウンドファイル

starting_address=0x80009000     # RAM領域データ設定開始アドレス #領域EEPPOMアドレスであれば(0x9D020000)
setting_limit_address=0x80009000+0x0F00 # 設定限界アドレス EEPPOM領域であれば(0x9D03E400)

path=r"C:\Microchip\umehoshiEdit\samples\_20240305\PB5_PWD\data.bin.hex"
print(f"starting_address:{setting_limit_address:016X}で「UME専用Hexファイル:{path}」を出力")

def getframedatas_by_wav(wav_file_path:str): # wavファイルからフレームレートと、16bitPCMバイナリーを取得
   print(f"{wav_file_path}サウンドファイルから、再生用のバイト列を取得")
   wavefile = wave.open(wav_file_path, "r")
   framerate = wavefile.getframerate() # フレームレート(1秒間のデータ出力数)
   print(f"フレームレート:{framerate}Hz、サンプリング周期:{1/framerate*1e6:6.2f}u秒") 
   nchannel=wavefile.getnchannels()
   print("チャンネル数:", nchannel)
   sampwidth=wavefile.getsampwidth()
   print("サンプル幅数:", sampwidth)
   if sampwidth != 2:
      print(f"サンプル幅数が2(PCM 16bit)以外に対応していません")
      exit()
   nframes = wavefile.getnframes() # 全フレーム内データ数
   print(f"フレームの数:{nframes}, 時間:{nframes/framerate}秒") 
   buffer = wavefile.readframes(nframes) # 全フレームを読み取る
   wavefile.close() # ファイルを閉じる 
   if nchannel == 2: # 2チャンネルであれば、左チャンネルだけ抽出
      ba=bytearray()
      for i,c in enumerate(list(buffer)):
         if i%4==0: ba.append(c)# 左チャンネル抽出(0,1)、右なら(3,4)
         if i%4==1: ba.append(c)
      buffer = bytes(ba)
   return framerate, buffer

framerate, buffer=getframedatas_by_wav(WAV_FILE_PATH) # wavファイルからフレームレートと、16bitPCMバイナリーを取得

print(f"オリジナルのサウンドの{len(buffer)/2/framerate} 秒を再生する。")
import pyaudio # サウンド再生用
audio = pyaudio.PyAudio()
format=audio.get_format_from_width(width=2) # ストリームを読み書きするときのデータ型
stream = audio.open(format=format,channels=1,rate=framerate,output=True)
stream.write(buffer)  # オリジナルのサウンドの音を確認

print(f"サウンドデータ(16bitPCMバイナリー)からpulse_modulationで使う値(符号なし16bitのnumpy配列)に変換")
int16_np=np.frombuffer(buffer, dtype="int16")
uint16_np=int16_np+(2<<14) # int16をunsigned int 16へ
time_array=[n * (1/framerate) for n in range(len(uint16_np))] # 過度特性の時間プロットデータ

#uint16_np=np.array([getTestSingnal(t*5e-6) for t in range(int(20e-3/5e-6))], np.uint16) # uint16_nにテストデータを使う
#time_array=[t*5e-6 for t in range(int(20e-3/5e-6))] # 上記テストデータの時間プロットデータ

plt.subplot(5, 1, 1)
plt.plot(time_array,uint16_np)  # オリジナルのサウンド(uint16)の視覚化

def getSingnal(elapsed_time: float): # 外部リスト変数のuint16_nを参照し、経過時間から信号源のデータを得る
    period = time_array[1]
    idx=int(elapsed_time/period)
    if idx >= len(uint16_np) : idx = len(uint16_np)-1 # 最後のデータ
    val = uint16_np[idx]
    return val

# 積分回路を通す
uint16_np=uint16_np.astype(np.float) # getSingnal入力源を変更
R1=1.2e3
C1=1e-6
v0=getSingnal(0)
q1=v0*C1
Vc1_list = integral_circuit(getSingnal, time_array, R1 , C1, q1 , dt=0.5e-6) # 積分回路の出力リスト
plt.subplot(5, 1, 2)
plt.plot(time_array, Vc1_list) # シミュレーション結果のアナログプロット

# 微分回路を通す 
uint16_np=Vc1_list # getSingnal入力源を変更
R1=2.2e3
C1=1e-6
v0=getSingnal(0)
q1=v0*C1
Vc1_list = differentiator(getSingnal, time_array, R1 , C1, q1 , dt=0.5e-6) # 微分回路の出力リスト
plt.subplot(5, 1, 3)
plt.plot(time_array, Vc1_list) # シミュレーション結果のアナログプロット

# Vc1_listをuint16 に変換してuint16_npにセット
uint16_np=np.array(Vc1_list)-min(Vc1_list) # 負のデータを無しに調整
uint16_np*=65535/max(uint16_np) # 0から65535に調整
uint16_np=uint16_np.astype(np.uint16) # 符号無し整数に変換
plt.subplot(5, 1, 4)
plt.plot(time_array, uint16_np) 
#plt.show()


minV=min(uint16_np)
value_width=max(uint16_np)-minV
print(f"最小値:{minV}, 値の幅:{value_width}")
print(f"データ数:{uint16_np.shape[0]}")

NREP=6 # 1つ(4bit)のデータを、約(1/4410)秒周期で繰り返し使う回数(水平分解能指定パラメタ)
count_out=0 # NREPの回数カウント用で、この回数分のデータ
nrep_list =[]
prev_val=0
print(f"サウンドデータ(16bitPCMバイナリーのuint16_np)を4bitデータに変換し、{NREP}個のサンプル数を1つまとめる")
datas_4bit=[] # 4bitに変換したデータの記憶用リスト
for i in range(uint16_np.shape[0]):
    val= uint16_np[i]
    nrep_list.append(val)
    count_out+=1
    if count_out == NREP:
       val=nrep_list[0]
       val=sum(nrep_list)/len(nrep_list) # ここで、データの変化に対応した特殊抽出の制御検討が可能
       if val > prev_val : val = max(nrep_list)
       elif val < prev_val : val = min(nrep_list)
       prev_val=val
       idx_v= int( (val-minV)/value_width*16 )
       idx_v = 15 if idx_v >= 16 else idx_v 
       datas_4bit.append(idx_v)
       count_out=0
       nrep_list =[]

print(f"最小値:{min(datas_4bit)}, 最大値:{max(datas_4bit)}")
print(f"データ数:{uint16_np.shape[0]}から{len(datas_4bit)}個になった。")
plt.subplot(5, 1, 5)
plt.plot(datas_4bit)
plt.show() 

# datas_4bitの4bitデータリストを内容を4096倍してバイナリ化し、その音を再生
buffer2=(np.array( [[x<<12]*NREP for x in datas_4bit] ).flatten()-(2<<14)).astype(np.int16).tobytes()
stream.write(buffer2)  # 変換した音を確認

print("4ビット要素の2つを、1バイトにまとめて、リストにする。")
bin_data_array=[]
for n,bit4 in enumerate(datas_4bit): # (249600バイト以下にしないとリンクエラーの可能性あり)
    if n % 2 == 0:
        v = bit4
    else:
        v |= bit4<<4
        bin_data_array.append(v)
        #print(f" '\\x{v:02X}',", end="")

print(f"生成したデータ:{len(bin_data_array)}byte")

def data_to_ume_hex_faile(path, datas_list, starting_address, limit_address):
    'datas_listが8bitデータのリストのファイル化で、starting_addressの番地から'
    'UMEHOSHI ITA用の「S」から始まる設定データ群を「UME専用Hexファイル」として出力'
    idx=0
    address16 = starting_address
    with open(path, "w") as f: # UMEHOSHI C言語配列用パルス変調のデータを書き込み
        while idx < len(datas_list) and address16 < limit_address:
            nn = 16
            if idx+nn >= len(datas_list):nn = len(datas_list)-idx
            if address16+nn >= limit_address:nn = limit_address-address16
            s=f"S{nn:02X}{address16:08X}00"
            for n in range(nn):
                s+=f"{datas_list[idx+n]:02X}"
            checksum=sum([ord(c) for c in s])
            s+=f"{((0x100-checksum)) & 0x0ff:02X}"
            #print(s)
            f.write(f"{s}\n")
            idx += nn
            address16+=nn
        return address16

last_address=data_to_ume_hex_faile(path, bin_data_array, starting_address, setting_limit_address)
print(f"last_address:{last_address:016X}, {last_address-starting_address}byteのデータ")
上記の  の部分で、integral_circuitモジュールの積分と微分を使っています。
このモジュールのソースコードを下記に示します。
from typing import Callable

# 積分回路のシミュレーション関数
def integral_circuit(getV1:Callable, time_array:list,  R1:float , C1:float, q1=0 , dt=0.5e-6)->list:
    '第1引数:getV1は経過時間を引数にしてその時の入力電圧を返す関数を登録するための引数'
    '第2引数:time_arrayのリスト要素のタイミングで戻り値ので出力電圧のリストが作る'
    '第3,4引数:R1は積分回路の抵抗値(単位はオーム)と、C1はコンデンサ(単位はファラット)'
    '第5,6引数:q1はCに蓄えられた初期電荷(単位はクローン)と、dtはシミュレーションで使う微小時間(単位は秒)'
    Vc1_list=[q1/C1]
    time_idx=1
    time_next=time_array[time_idx]
    time_now=0
    while True:
        v1=getV1(time_now)
        i=(v1-q1/C1)/R1
        q1+=i*dt
        time_now+=dt
        #print('-', end="")
        if time_now > time_next:
            #print(f"{time_idx:5}:{time_now:10.7f}, {q1/C1}v")
            Vc1_list.append(q1/C1)
            time_idx+=1
            if time_idx >= len(time_array): break
            time_next=time_array[time_idx]
    return Vc1_list

# 微分回路のシミュレーション関数
def differentiator(getV1:Callable, time_array:list,  R1:float , C1:float, q1=0 , dt=0.5e-6)->list:
    '第1引数:getV1は経過時間を引数にしてその時の入力電圧を返す関数を登録するための引数'
    '第2引数:time_arrayのリスト要素のタイミングで戻り値ので出力電圧のリストが作る'
    '第3,4引数:R1は積分回路の抵抗値(単位はオーム)と、C1はコンデンサ(単位はファラット)'
    '第5,6引数:q1はCに蓄えられた初期電荷(単位はクローン)と、dtはシミュレーションで使う微小時間(単位は秒)'
    time_now=0
    v1=getV1(time_now)
    Vc1_list=[v1-q1/C1]
    time_idx=1
    time_next=time_array[time_idx]
    while True:
        v1=getV1(time_now)
        i=(v1-q1/C1)/R1
        q1+=i*dt
        # print('-', end="")
        if time_now > time_next:
            # print(f"{time_idx:5}:{time_now:10.7f}, {q1/C1}v")
            Vc1_list.append(v1-q1/C1)
            time_idx+=1
            if time_idx >= len(time_array): break
            time_next=time_array[time_idx]
        time_now+=dt
    return Vc1_list

# 信号の変化を示すテストデータと関連関数------------------------------
array=[(0,0), (5e-3,0),
(10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), (10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), (10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), 
(10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), (10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), (10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), 
(10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), (10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), (10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), 
(10e-6,3.3), (480e-6,3.3), (10e-6,0), (480e-6,0), 	   (550e-6,0), ] # 各要素のtapleで[0]のデータが前の要素からの経過時間、[1] がその経過時の電圧値

def getTestSingnal(elapsed_time: float): # 外部リスト変数のarrayを参照し、経過時間から信号源のデータを得る
    prev_cumul_time=array[0][0] # 繰り返しで、前の経過時間 
    prev_val=array[0][1]
    i=1
    len_array = len(array)
    while i < len_array :
        cumul_time = prev_cumul_time + array[i][0] # 経過時間
        #print( i, cumul_time ,elapsed_time)
        if cumul_time >= elapsed_time :
            gradient=(array[i][1]-prev_val)/(array[i][0])
            val=gradient*(elapsed_time-prev_cumul_time) + prev_val
            return val
        prev_cumul_time = cumul_time
        prev_val=array[i][1]
        i+=1
    #
    return array[i-1][1] 


if __name__ == '__main__':
    import matplotlib.pyplot as plt
    time_array=[v * 5e-6 for v in range(int(20e-3/5e-6))] # 過度特性の時間プロットデータ
    val_array=[getTestSingnal(x) for x in time_array]   # 回路の入力電圧のプロットデータ
    plt.plot(time_array, val_array) # 入力源のデータをセット
    Vc1_list = integral_circuit(getTestSingnal, time_array, R1=2.2e3 , C1=1e-6, q1=0 , dt=0.5e-6) # 積分回路の出力リスト
    plt.plot(time_array, Vc1_list) # 積分回路の出力のプロット
    Vc1_list = differentiator(getTestSingnal, time_array, R1=2.2e3 , C1=1e-6, q1=0 , dt=0.5e-6) # 積分回路の出力リスト
    plt.plot(time_array, Vc1_list) # 積分回路の出力のプロット
    plt.show()
前述のwav_to_UME.pyは、上記モジュールの積分と微分の関数を利用いています。
オリジナルサウンド(16ビットPCM)の入力源を積分回路を通し、 この出力を微分回路に使って、その出力をPWM用の4ビットに変換しています。

積分回路で細かい雑音元になる情報を除去し、 微分回路で強調した部分を抽出して圧電ブザーに対する音圧を上げる効果を期待してみました。
実行時のコンソール画面例を示します。
C:\Users\suzuki\Music>python wav_to_UME.py
starting_address:0000000080009F00で「UME専用Hexファイル:C:\Microchip\umehoshiEdit\samples\_20240305\PB5_PWD\data.bin.hex」を出力
え_何.wavサウンドファイルから、再生用のバイト列を取得
フレームレート:48000Hz、サンプリング周期: 20.83u秒
チャンネル数: 2
サンプル幅数: 2
フレームの数:41414, 時間:0.8627916666666666秒
オリジナルのサウンドの0.8627916666666666 秒を再生する。
サウンドデータ(16bitPCMバイナリー)からpulse_modulationで使う値(符号なし16bitのnumpy配列)に変換
最小値:0, 値の幅:65534
データ数:41414
サウンドデータ(16bitPCMバイナリーのuint16_np)を4bitデータに変換し、6個のサンプル数を1つまとめる
最小値:0, 最大値:15
データ数:41414から6902個になった。
4ビット要素の2つを、1バイトにまとめて、リストにする。
生成したデータ:3451byte
C言語用の配列初期化データを、テキストファイルとして出力(最大で2950バイトの出力制限)
last_address:0000000080009D7B, 3451byteのデータ

C:\Users\suzuki\Music>
上記の実行で、"え_何.wav"のサウンドファイルのオリジナル音と、変換後の音がPC上で確認できます。
そして、[UMEHOSHI ITA]で使う3451byteのデータが生成され、それを、[UMEHOSHI ITA]に埋め込むための「UME専用Hexコマンド」ファイルが生成されます。
このファイル("data.bin.hex")の内容の一部を下記に示します。
S108000900000777777777777777777777777777777777B
S1080009010007777777777888888888888888888888864
 ・・・・・
これを[UMEHOSHI ITA]にUSB経由で転送すれば、上記で作られたサウンドのPWDのデータで 0x80009000のアドレスに、 3451バイトが設定されます。

この転送は「umehoshiEdit」ツールを使うと簡単にできます。
このツールの使い方は、「ビルドでできた.hexファイル」を[UMEHOSHI ITA]にUSBを介して転送のリンクを参照してください。

次に転送したデータの記憶域を指定して鳴らす実行をします。それには前述のC言語ソースをビルドして、実行コマンドを送ります。

以下で、オリジナルの音、目標、実験で鳴った音(録音)、などの実験結果を示します。

オリジナルファイル("え_何.wav")44100Hz,16BitPCM

オリジナルファイル16bitを、積分、微分、増幅、後に分解能4ビットに変換してPCで鳴らした音
なお、上記の積分回路や微分回路の時定数が最も適正かどうかの実験もしていません。

オリジナルのデータ6個から1個を抽出した目標となる音
目標となる音(音質を落としたデータでPC上のPythonで鳴らした音)
上記と同じで、オリジナルファイル16bitを、積分、微分、増幅、後に分解能4ビットに変換ししたデータを使って圧電サンダーで鳴らした音

残念ながら大きな効果が得られませんでした。
数値的に良くなった検証をしていませんが、少し雑音が減ってインパクトが付いた感じで、チョット聴きやすくなったように感じます。
音量は大きく感じられませんでした。
上記と同じで、オリジナルファイル16bitを、積分、微分、増幅、後に分解能4ビットに変換ししたデータを使ってスピーカーで鳴らした音

手持ちのスピーカーで、制限抵抗を2.2Kから47Ωに変更して実験した結果で、こちらの方が聞き取れました。


上記で作成したpb5_pwd関数を、「テスト・ウメ・フラッシュ」のAPIのようにROMに書き込んで、すぐ呼び出せるように使う例を、 このページで示します