PianoHat for MIDI
2024.03.23
YouTube でも紹介しています。画像をクリックすると再生できます。
USB-MIDI
2022年9月16日「USB-MIDI」では、MIDIキーボードコントローラーをUSB HOST SHIELDに接続しUNOに被せてMIDIコマンドを受け取り、
MUSIC MAKERに流し込むことで音を出していました。
今回はRaspberry Piの拡張ボードであるPIMORONI Piano HAT を入力デバイスとして使用します。
●Piano HAT
PIMORONI Piano HAT はラズベリーパイに被せて使う拡張ボードです。
Piano HAT アプリをインストールするとピアノ88鍵分の音声ファイル88個といつくかのドラムの音源がPianoHATのディレクトリに保存されます。
鍵盤を叩くと音が出て、右上の[OCTAVE▼]、[OCTAVE▲]で音域を切り替え、[INSTRUMENT]でピアノとドラムを切り替えることができます。
また、Piano HATのサンプルコードは、Pythonで記述されています。
ここでは、Piano HATとESP32をI2C接続して、Piano HATに搭載されているCAP1188センサーの情報を取得します。
●補足
以前
Zero 2 W と Bullseye
で取り上げましたが、Piano HATモジュールは、Python 2 用のライブラリに依存していて、Python3の環境では動作しません。
Pimoroni Piano HAT と DAWソフトウェア Rosegarden を連携するための、midi-sequencerでエラーがでていました。
AttributeError: module 'midi.sequencer' has no attribute 'SequencerHardware'
●CAP1188
Piano HATの鍵盤にはAdafruit CAP1188 8Key Capacitive Touch Sensor Breakout と同様に CAP1188 I2C/SPI 8-Channel Capacitive Sensor(静電容量タッチセンサ)が使われています。
人間の身体は導体として働くため、人の指先がタッチパネルに近づくと、指先とセンサー電極間に、コンデンサのような静電容量が発生します。
この静電容量の変化を検知するのが静電容量式センサーです。
1個のCAP1188チップは8チャンネルなので、Piano HATでは2個のCAP1188チップを使用しています。
Adafruit CAP1188 Breakout > Using with Arduino
●Adafruit QT Py ESP32-S2 WiFi Dev Board with STEMMA QT
マイコンボードには、Adafruit QT Py ESP32-S2 を使用しています。Piano HATの鍵盤をタッチして音を鳴らす際の音源は、
メモリ上に配置しているので、2MBのPSRAMを実装しているESP32-S2は便利です。
・ESP32-S2 240MHz
・4 MB Flash & 2 MB PSRAM
・2.4 GHz Wi-Fi (SoC)
・Two I2C ports
・Hardware UART
・Hardware SPI
・Hardware I2S on any pins
・3.3V regulator with 600mA peak output
Ref.Adafruit QT Py ESP32-S2
●Qt Py ESP32-S2 Pinout
●Piano HAT Pinout
Piano HAT at Raspberry Pi GPIO Pinout
・鍵盤上のLEDを光らせないのであれば、5V Power供給は不要です
・GPIO4,27のAlertピンのいずれかをGNDに接続すれば正常に動作します。
・GPIO17,22のResetピンは非接続で大丈夫です。
・2個のCAP1188のアドレスは 0x28 と 0x2b です。
0x28:C,C#,D,D#,E,F,F#,G
0x2b: G#,A,A#,B,C,Instrument,Octave -,Octave +
●Nano HAT Hacker
Piano HATは本来ラズベリーパイに被せて使うものなので、GPIOピンを引き出す必要があります。
Nano HAT Hacker は本来GPIO分岐に用いるのですが、これは便利です。
40pinピンヘッダーを2個はんだ付けして使います。
●組み立て
UNO | - | レベル変換 | - | ESP32 | - | MusicMaker |
| | | | TXD | - | RX |
TXD | - | HV1-LV1 | - | A2 | | |
RXD | - | HV2-LV2 | - | (A3) | | |
5V | - | 5V-3.3V | - | 3.3V | - | 3V |
GND | - | GND-GND | - | GND | - | GND |
PianoHat | | | | | | |
SDA | - | --------- | - | SDA | | |
SCL | - | --------- | - | SCL | | |
3.3 | - | --------- | - | 3.3V | | |
GND | - | --------- | - | GND | | |
| | | | | | Battery |
5V※ | - | --------- | - | 5V | - | 5V |
※PianoHatの5V端子はLED点灯に使用されますが、QT Pyの5V出力は脆弱なため、5V電源から直接供給します。
左側のUSB HOST SHIELDは今回関係ありません。
右側、ブレッドボードに縦に刺さっている基板上にMUSIC MAKERを取り付けています。
基板の背面に Adafruit QT Py ESP32-S2を取り付けていますi。
演奏の際には、MUSIC MAKERの3.5mm AUDIO OUT端子にアンプ内蔵のスピーカーなどを繋ぎます。
うぷ主は、LINE-IN端子のある充電式ラジオを使っています。
●gitHub
下記gitHubのサンプルコードを参考にして、ESP32用のArduinoコードを作成しました。
adafruit/Adafruit_CAP1188_Library
・Adafruit_CAP1188.cpp
・cap1188test.ino
pimoroni/cap1xxx
・cap1xxx.py
pimoroni/Piano-HAT
・pianohat.py
ソースコード
#include <Wire.h>
#define VS1053_BANK_DEFAULT 0x00
#define GM_ACOUSTIC_PIANO 0x00
#define VELOCITY_FFF 112
#define MIDI_NOTE_ON 0x90
#define MIDI_NOTE_OFF 0x80
#define MIDI_CHAN_MSG 0xB0
#define MIDI_CHAN_BANK 0x00
#define MIDI_CHAN_VOLUME 0x07
#define MIDI_CHAN_PROGRAM 0xC0
#define I2C_CAP1188_A 0x28
#define I2C_CAP1188_B 0x2B
#define CAP1188_RESET_A -1
#define CAP1188_RESET_B -1
#define R_SENSOR_THRESHOLD 0x30
#define R_LED_BEHAVIOUR_1 0x81
#define R_LED_BEHAVIOUR_2 0x82
#define R_LED_LINKING 0x72
#define R_SAMPLING_CONFIG 0x24
#define R_SENSITIVITY 0x1F
#define R_GENERAL_CONFIG 0x20
#define R_CONFIGURATION2 0x44
#define R_LED_DIRECT_RAMP 0x94
#define CAP1188_SENINPUTSTATUS 0x3
#define CAP1188_MTBLK 0x2A
#define CAP1188_LEDLINK 0x72
#define CAP1188_PRODID 0xFD
#define CAP1188_MANUID 0xFE
#define CAP1188_STANDBYCFG 0x41
#define CAP1188_REV 0xFF
#define CAP1188_MAIN 0x00
#define CAP1188_MAIN_INT 0x01
#define CAP1188_LEDPOL 0x73
uint8_t keyPrev[128];
uint8_t keyStatus[128];
#define command(Adr,Reg) I2C_Write_Byte(Adr, Reg, 0x00)
#define data(Adr,Data) I2C_Write_Byte(Adr, Data, 0x40)
uint8_t octave = 4;
int8_t subnote;
#define CHANNEL_0 0
void _delay(uint32_t msec) {
portTickType delay_ms = msec / portTICK_RATE_MS;
vTaskDelay(delay_ms);
}
void midiout_write(uint8_t value) {
Serial1.write(value);
}
void setChannelBank(uint8_t channel, uint8_t bank)
{
midiout_write(MIDI_CHAN_MSG | channel);
midiout_write((uint8_t)MIDI_CHAN_BANK);
midiout_write(bank);
}
void setInstrument(uint8_t channel, uint8_t instrument)
{
midiout_write(MIDI_CHAN_PROGRAM | channel);
midiout_write(instrument);
_delay(10);
}
void send(uint8_t status, uint8_t data1, uint8_t data2)
{
midiout_write(status);
midiout_write(data1);
midiout_write(data2);
}
void change(uint8_t status, uint8_t data)
{
midiout_write(status);
midiout_write(data);
}
void I2C_Write_Byte(uint8_t addr, uint8_t Cmd, uint8_t value)
{
Wire.beginTransmission(addr);
Wire.write(Cmd);
Wire.write(value);
Wire.endTransmission();
}
uint8_t readRegister(uint8_t addr, uint8_t Cmd)
{
int val;
Wire.beginTransmission(addr);
Wire.write(Cmd);
Wire.endTransmission();
Wire.requestFrom(addr, 1);
while (Wire.available() > 0) {
val = Wire.read();
}
return (uint8_t)val;
}
uint8_t cap1188_touched(uint8_t addr) {
uint8_t t = readRegister(addr, CAP1188_SENINPUTSTATUS);
if (t) {
I2C_Write_Byte(addr, CAP1188_MAIN, readRegister(addr, CAP1188_MAIN) & ~CAP1188_MAIN_INT);
}
return t;
}
boolean cap1188_setup(uint8_t addr, int8_t reset) {
uint8_t pid, mid, rev;
if (reset >=0 ) {
pinMode(reset, OUTPUT);
digitalWrite(reset, LOW);
_delay(100);
digitalWrite(reset, HIGH);
_delay(100);
digitalWrite(reset, LOW);
_delay(100);
}
// Useful debugging info
pid = readRegister(addr, CAP1188_PRODID);
mid = readRegister(addr, CAP1188_MANUID);
rev = readRegister(addr, CAP1188_REV);
if ((pid != 0x50) || (mid != 0x5D) || (rev != 0x83)) return false;
I2C_Write_Byte(addr, CAP1188_MTBLK, 0);
I2C_Write_Byte(addr, CAP1188_LEDLINK, 0xFF);
I2C_Write_Byte(addr, CAP1188_STANDBYCFG, 0x30);
for (int i=0;i<8;i++) I2C_Write_Byte(addr, R_SENSOR_THRESHOLD + i, 0b00000110);
I2C_Write_Byte(addr, R_LED_BEHAVIOUR_1, 0b00000000);
I2C_Write_Byte(addr, R_LED_BEHAVIOUR_2, 0b00000000);
I2C_Write_Byte(addr, R_LED_LINKING, 0b11111111);
I2C_Write_Byte(addr, R_SAMPLING_CONFIG, 0b00000000);
I2C_Write_Byte(addr, R_SENSITIVITY, 0b01100000);
I2C_Write_Byte(addr, R_GENERAL_CONFIG, 0b00111000);
I2C_Write_Byte(addr, R_CONFIGURATION2, 0b01100000);
I2C_Write_Byte(addr, R_LED_DIRECT_RAMP, 0);
memset(keyPrev,0x00,128);
return true;
}
boolean cap1188_init(TwoWire *wire)
{
wire->beginTransmission(I2C_CAP1188_A);
if (wire->endTransmission() != 0) {
return false;
} else {
if (!cap1188_setup(I2C_CAP1188_A, CAP1188_RESET_A)) {
return false;
}
}
wire->beginTransmission(I2C_CAP1188_B);
if (wire->endTransmission() != 0) {
return false;
} else {
if (!cap1188_setup(I2C_CAP1188_B, CAP1188_RESET_B)) {
return false;
} else {
return true;
}
}
}
void cap1188_keyon(int oct,int subnote)
{
int noteNo = 12 * (oct + 1) + subnote;
keyStatus[noteNo] = 1;
}
void cap1188_play()
{
for (int no=0; no<128; no++) {
if ((keyPrev[no]==1)&&(keyStatus[no]==0)) {
keyPrev[no] = 0;
noteOff(CHANNEL_0|0x80, no, 0);
} else if ((keyPrev[no]==0)&&(keyStatus[no]==1)) {
keyPrev[no] = 1;
noteOn(CHANNEL_0|0x90, no, VELOCITY_FFF);
}
}
}
void cap1188_status()
{
memset(keyStatus, 0x00,128);
uint8_t touchedA = cap1188_touched(I2C_CAP1188_A);
uint8_t touchedB = cap1188_touched(I2C_CAP1188_B);
if (touchedA & 0x01) cap1188_keyon(octave, 0);
if (touchedA & 0x02) cap1188_keyon(octave, 1);
if (touchedA & 0x04) cap1188_keyon(octave, 2);
if (touchedA & 0x08) cap1188_keyon(octave, 3);
if (touchedA & 0x10) cap1188_keyon(octave, 4);
if (touchedA & 0x20) cap1188_keyon(octave, 5);
if (touchedA & 0x40) cap1188_keyon(octave, 6);
if (touchedA & 0x80) cap1188_keyon(octave, 7);
if (touchedB & 0x01) cap1188_keyon(octave, 8);
if (touchedB & 0x02) cap1188_keyon(octave, 9);
if (touchedB & 0x04) cap1188_keyon(octave,10);
if (touchedB & 0x08) cap1188_keyon(octave,11);
if (touchedB & 0x10) cap1188_keyon(octave,12);
if (touchedB & 0x20) { if (octave > 1 ) octave--; while(cap1188_touched(I2C_CAP1188_B));};
if (touchedB & 0x40) { if (octave < 7 ) octave++; while(cap1188_touched(I2C_CAP1188_B));};
if (touchedB & 0x80) { while(cap1188_touched(I2C_CAP1188_B));};
cap1188_play();
}
void setChannelVolume(uint8_t channel, uint8_t vol)
{
midiout_write(MIDI_CHAN_MSG | channel);
midiout_write(MIDI_CHAN_VOLUME);
midiout_write(vol);
}
void noteOn(uint8_t command, uint8_t note, uint8_t velocity)
{
midiout_write(command);
midiout_write(note);
midiout_write(velocity);
_delay(10);
}
void noteOff(uint8_t command, uint8_t note, uint8_t velocity)
{
midiout_write(command);
midiout_write(note);
midiout_write(velocity);
_delay(10);
}
void setup()
{
Serial1.begin(31250); // midi out
Wire.begin();
cap1188_init(&Wire);
setChannelBank(CHANNEL_0, VS1053_BANK_DEFAULT);
setChannelVolume(CHANNEL_0, VELOCITY_FFF);
setInstrument(CHANNEL_0, GM_ACOUSTIC_PIANO);
}
void loop()
{
cap1188_status();
}
プログラム概要
MIDIコントローラー(キーボード)とPiano HAT との違いは、MIDIコマンドの検出方法です。
MIDIコントローラーでは、鍵盤が押されると、NOTE ONのコマンドが1回のみ送信され、鍵盤を離したときに1回、NOTE OFFのコマンドが送信されます。
待ち受け側のマイコン側では、受信したコマンドを評価して、MUSIC MAKERに送信します。
これに対して、Piano HATでは、マイコン側から、Piano HATに問い合わせを行い、ステータス情報を取得します。
PianoHatは2つのCAP1188タッチセンサが搭載されており、i2Cアドレスはと0x28と0x2Bです。
各々のレジスタ0x03には1バイト・ステータス値の各ビットが8つのキー(鍵盤)に対応しており、ビットに1が立っているものが押されたキーを表しています。
0x28:C,C#,D,D#,E,F,F#,G
0x2b: G#,A,A#,B,C,Instrument,Octave -,Octave +
void loop()
{
cap1188_status();
}
マイコン側はloop()処理により、CAP1188センサーの状態を取得しています。
void cap1188_status()
{
memset(keyStatus, 0x00,128);
uint8_t touchedA = cap1188_touched(I2C_CAP1188_A);
uint8_t touchedB = cap1188_touched(I2C_CAP1188_B);
if (touchedA & 0x01) cap1188_keyon(octave, 0);
if (touchedA & 0x02) cap1188_keyon(octave, 1);
if (touchedA & 0x04) cap1188_keyon(octave, 2);
if (touchedA & 0x08) cap1188_keyon(octave, 3);
if (touchedA & 0x10) cap1188_keyon(octave, 4);
if (touchedA & 0x20) cap1188_keyon(octave, 5);
if (touchedA & 0x40) cap1188_keyon(octave, 6);
if (touchedA & 0x80) cap1188_keyon(octave, 7);
if (touchedB & 0x01) cap1188_keyon(octave, 8);
if (touchedB & 0x02) cap1188_keyon(octave, 9);
if (touchedB & 0x04) cap1188_keyon(octave,10);
if (touchedB & 0x08) cap1188_keyon(octave,11);
if (touchedB & 0x10) cap1188_keyon(octave,12);
if (touchedB & 0x20) {
if (octave > 1 ) octave--;
while(cap1188_touched(I2C_CAP1188_B));
};
if (touchedB & 0x40) {
if (octave < 7 ) octave++;
while(cap1188_touched(I2C_CAP1188_B));
};
if (touchedB & 0x80) {
while(cap1188_touched(I2C_CAP1188_B));
};
cap1188_play();
}
void cap1188_keyon(int oct,int subnote)
{
int noteNo = 12 * (oct + 1) + subnote;
keyStatus[noteNo] = 1;
}
void cap1188_play()
{
int subnote, oct;
for (int no=0; no<128; no++) {
if ((keyPrev[no]==1)&&(keyStatus[no]==0)) {
keyPrev[no] = 0;
noteOff(CHANNEL_0|0x80, no, 0);
} else if ((keyPrev[no]==0)&&(keyStatus[no]==1)) {
keyPrev[no] = 1;
noteOn(CHANNEL_0|0x90, no, VELOCITY_STD);
}
}
}
鍵盤の状態が変化した場合にのみ、MUSIC MAKER にMIDIコマンドを送信しています。
●演奏
鍵盤をタッチすると、押された鍵盤上部のLEDが光り、スピーカーから音が流れます。
掲載ソースでは、アコースティック・ピアノGM音源固定ですが、
[INSTRUMENT]ボタンを押すたびにお気に入りの音色を変えるとよいかもしれません。
●応用
掲載ソースは最低限必要なコードになっていますが、
実際にはTelnet端末にMIDIコードを表示すると同時にログを保存しています。
鍵盤の状態のほかに音の間隔(デルタ・タイム)も算出しています。
デルタ・タイムがゼロの箇所は同時に複数の鍵盤を押しています。
記録したメロディーのお気に入り箇所を抜き出し、先頭のMIDIコードを用いて再現できるようにしています。
|
Raspberry Pi(ラズベリー パイ)は、ARMプロセッサを搭載したシングルボードコンピュータ。イギリスのラズベリーパイ財団によって開発されている。
Arduinoで学ぶ組込みシステム入門(第2版)
●Arduinoを使って組込みシステム開発を理解する
・ハードウェアやソフトウェアなどの基礎知識/
・設計から実装までを系統的に説明するモデルベース開発/
・Arduinoを用いた実際の開発例
最新 使える! MATLAB 第3版
◆◆すぐに「使える!」 全ページフルカラー!◆◆
・MATLAB R2022bに対応し、解説もより詳しく!/
・コマンド・スクリプトの例が豊富で、動かして学べる!/
・超基本から解説。これから使いはじめる人にぴったり!/
・全編フルカラー、スクリーンショットも豊富!
Amazon Web Services基礎からのネットワーク&サーバー構築改訂4版
1.システム構築をインフラから始めるには/
2.ネットワークを構築する/
3.サーバーを構築する/
4.Webサーバーソフトをインストールする/
5.HTTPの動きを確認する/
6.プライベートサブネットを構築する/
7.NATを構築する/
8.DBを用いたブログシステムの構築/
9.TCP/IPによる通信の仕組みを理解する
C言語は第二の母国語: 独学学生時代から企業内IT職人時代に培った、独立のための技術とノウハウ 平田豊著
学生時代から独学でプログラミングをはじめ、企業内でデバイスドライバを開発し、そして独立後もたくさんのアプリケーション開発や技術書制作に携わってきた著者。その筆者が大事に使い続ける「C言語」の“昔と今”について、気づいたことや役立つ知識、使ってきたツールなどについて、これまで記してきたことを整理してまとめました。
本書では、現役プログラマーだけでなく、これからプログラミングを学ぶ学生などにも有益な情報やノウハウを、筆者の経験を元に紹介しています。
1冊ですべて身につくJavaScript入門講座
・最初の一歩が踏み出せる! 初心者に寄り添うやさしい解説
・最新の技術が身につく! 今のJavaScriptの書き方・使い方
・絶対に知っておきたい! アニメーションとイベントの知識
・プログラミングの基本から実装方法まですべて学べる
図解! Git & GitHubのツボとコツがゼッタイにわかる本
ソフトウェア開発では欠かすことのできないGit、GitHub。
これからGit、GitHubを使いたいという入門者の方でも、実際に手を動かしながら使い方を学べます。
C自作の鉄則!2023 (日経BPパソコンベストムック)
メーカー製のパソコンはスペックが中途半端で、自分が本当に欲しい機種がない――。そう思っている人には、ぜひ自作パソコンをお薦めします。自作パソコンのパーツは進化が速く、しかも驚くほど種類が豊富。価格も性能も、幅広く用意されているため、満足度100%の“自分だけの1台”を手に入れることができます。
Interface 2023年6月号
特集:第1部 フィルタ設計 基礎の基礎/
第2部 係数アプリや波形観測アプリで合点!FIR&IIRフィルタ作り/
第3部 配布プリント基板で体験!マイコンで動くフィルタ作り
日経Linux 2023年5月号
【特集 1】 AI時代の最強フリーソフト ~ 25のやりたいを実現!
【特集 2】 AWS、Azureのうまみを無料で体感!面倒なことはクラウドに任せよう
【特集 3】 新しいRaspberry Pi Cameraで遊んでみよう
【特集 4】 Linuxで旧型PCを復活! 1kg切るモバイルPCを「ChromeOS Flex」でChromebook化
ラズパイマガジン2022年秋号
特集:5大人気ボード 電子工作超入門
「半導体不足で在庫が不足し、電子工作のボードがなかなか買えない…」。そんな今にふさわしい特集を企画しました。5種の人気ボードにすべて対応した電子工作の入門特集です。「GPIO」や「I2C」を使った電子パーツの制御方法は、どのボードでも同じです。手に入れられたボードを使って、今こそ電子工作を始めましょう。
地方で稼ぐ! ITエンジニアのすすめ
学歴、理系の知識、専門スキル……全部なくてもITエンジニアになれる!
地方でも高収入でやりがいをもって働ける!ITエンジニアの魅力を一挙大公開
Raspberry Piのはじめ方2022
本書は、ラズパイやPicoの買い方やインストール、初期設定といった基本から、サーバー、電子工作、IoT、AIといったラズパイならではの活用方法まで、1冊でお届けします。
ラズパイをこれから始める方向けに、全36ページの入門マンガ「女子高生とラズベリーパイ」も巻末に掲載。これを読むだけでラズパイがどんなものなのか、すぐに分かって触れるようになります。
ハッカーの学校 IoTハッキングの教科書
生活にとけこみ、家電機器を便利にするIoT技術。
Webカメラなど、便利の裏側に潜むセキュリティの危険性をハッキングで検証。
専門家がパケットキャプチャからハードウェアハッキングまで、その攻撃と防御を徹底解説。
本書は2018年7月に刊行された「ハッカーの学校IoTハッキングの教科書」に一部修正を加えた第2版です。
攻撃手法を学んで防御せよ! 押さえておくべきIoTハッキング
本書は、経済産業省から2021年4月にリリースされた、IoTセキュリティを対象とした『機器のサイバーセキュリティ確保のためのセキュリティ検証の手引き』の『別冊2 機器メーカに向けた脅威分析及びセキュリティ検証の解説書』をもとに、IoT機器の開発者や品質保証の担当者が、攻撃者の視点に立ってセキュリティ検証を実践するための手法を、事例とともに詳細に解説しました。
ポチらせる文章術
販売サイト・ネット広告・メルマガ・ブログ・ホームページ・SNS…
全WEB媒体で効果バツグン!
カリスマコピーライターが教える「見てもらう」「買ってもらう」「共感してもらう」すべてに効くネット文章術
プログラマーは世界をどう見ているのか 西村博之著
イーロン・マスク(テスラ)、ジェフ・べゾス(Amazon)、ラリー・ペイジ(Google)…etc.
世界のトップはなぜプログラマーなのか?
ニーア オートマタ PLAY ARTS改 <ヨルハ 二号 B型 DX版> PVC製 塗装済み可動フィギュア
「NieR:Automata」より、ヨルハ二号B型こと2BがPLAY ARTS改に新たに登場!
高級感の感じられるコスチュームや髪の質感、洗練されたボディバランス、細かなデティールに至るまでこだわり抜かれた逸品。
DX版には通常版のラインナップに加え2Bの随行支援ユニット ポッド042などをはじめ“純白の美しい太刀"白の約定やエフェクトパーツ、自爆モードを再現できる換装用ボディパーツ、シーンに合わせて変えられる顔パーツ2種も付属する豪華な仕様に。
作中のあらゆるシーンを再現することが可能なファン必見の一品となっている。
Newtonライト2.0 ベイズ統計
ベイズ統計は,結果から原因を推定する統計学です。AIや医療などの幅広い分野で応用されています。その基礎となるのは18世紀に考えだされた「ベイズの定理」です。
この本では,ベイズ統計学のきほんをやさしく紹介していきます。
白光(HAKKO) ダイヤル式温度制御はんだ吸取器 ハンディタイプ FR301-81
無水エタノールP 500mlx2個パック(掃除)
ケイバ(KEIBA) マイクロニッパー MN-A04
サンハヤト SAD-101 ニューブレッドボード
白光(HAKKO) HEXSOL 巻はんだ 精密プリント基板用 150g FS402-02
[Amazon限定ブランド]【指定第2類医薬品】PHARMA CHOICE 解熱鎮痛薬 解熱鎮痛錠IP 100錠
|