airpocket が 2026年01月30日15時41分52秒 に編集
コメント無し
本文の変更
# ~~
「~~(なみなみ)」は、シリコーンオイルと水の二相界面に生じる波のダイナミクスを観察する装置です。
「~~(なみなみ)」は眺めているだけで心癒される。そして少し哲学的、科学的に思いを馳せることもできるかもしれない波を楽しむための装置です。
二相界面は、性質の異なる物質が接する境界であり、物理的・化学的ポテンシャルが集中する領域です。 界面では、粘性・密度・表面張力などの差が相互に作用し、わずかな外力でも大きな変形が生じることがあります。
皆さんが波という言葉を聞いて連想するとき、そのイメージはポジティブな印象、例えば雄大な海の波を想起される方が多いのでh内科と思います。。
「~~」では、電子制御された機械的な揺動により液体に外力を与え、界面がどのように応答するかを多角的に観察できます。 一定周期の揺動、ランダムな刺激、ゆっくりとした遷移など、条件が変わるだけで界面形状は大きく変化します。 同じ入力であっても、界面は整列、崩壊、反転、干渉を繰り返し、非線形系特有の多様な波形を示します。
ゆったりと大きく力強い、時には繊細な波が繰り返し打ち寄せる。でもよくよく見ると二度と同じ波は来ない。 そんなイメージの波を卓上でお手軽に楽しんでみたいな。という思いから作った装置です。
液体の運動は、界面が存在することによって初めて明瞭に可視化されます。 目に見えない物理的ポテンシャルが、波として現れ、形として記録されます。 「~~」は、その現象をコンパクトなスケールで観察可能なインスタレーションとして設計されています。
# ユニット交換式の卓上装置
@[youtube](]https://www.youtube.com/watch?v=jE8Rj6CCtNc)
# 波動ジェネレーターΨ
「~~」は電子制御を行うコントローラ部、モーターによる駆動部を隠したドライバ、透明のケースの中に造波装置を埋め込んだなみなみユニットの三つの部位に分かれています。 なみなみユニットは現在4台が稼働しています。 ポンと乗せ換えるだけで交換できて、動力は磁力を介して伝達しています。
水漏れ中
# ハードウェア構成図
波動ジェネレータΨは波の生成方法の研究用ポッドです。筒状の容器の両端に2種類の揺動装置を設置し、それぞれの波の形状を観察できます。

@[twitter](https://x.com/AirpocketRobot/status/1980628170786394433) 縦波を生成して共振周波数付近で揺動させると定常波として観察できます。
メカの構成は上手の通りです。 SPRESENSEでステッピングモーターを制御し、ロータリーエンコーダーでモーターの回転数を変更できます。 SPRESENSEと拡張基板、DC-DC降圧ボードは3Dプリンタ製のベースボードの上に固定していますが、筐体のカバーは設置せず基板はむき出し。ディスプレイとロータリーエンコーダは固定せずケーブル接続しただけです。
@[twitter](https://x.com/AirpocketRobot/status/1986960013739631013) 密閉しているため、角度を変えて波の断面を好きな角度で切り取れます。
ステッピングモーターは駆動部の筐体の中に隠し、外部からは見えないものの。なみなみユニットに動力を伝えていることは自明化と思います。
@[twitter](https://twitter.com/AirpocketRobot/status/1986959560633164204) @[twitter](https://x.com/AirpocketRobot/status/1986959560633164204) @[X](https://x.com/AirpocketRobot/status/1986959560633164204) 横波を発生させることもできます。
なみなみユニットは現在4種類をラインナップしています。駆動ユニットとは磁石で結合し、伝達された回転運動を種々の運動に変換して波を起こしています。
# なみなみユニット @[youtube](https://youtu.be/IVK1aeQ3ynU) なみなみユニットの動きは上の動画の通りです。
## 物体Aの運動と波及 一つ目の装置は、一目みただけで、波を作る機構部が波を起こす様子を理解できます。 ダイナミックかつシンプルな波です。 しかしながら細部を見ると同じ波は一つとして存在していないことにも気づきます。 シンプルなオブジェクトの動きが、シンプルさと複雑さの両方を引き起こす波の魅力の根幹を表しています
## 1/323,323 二つ目の装置は、4枚のフィンの組み合わせがランダムな波を起こすことを狙っています。 フィンを駆動する歯車はそれぞれ異なる素数枚の歯をもっており、323,323回転に1回だけフィンが同期します。 シンプルな回転運動が静かではあるけれど複雑な状態を引き起こすという構造により、複雑な現象とメカ的な機構の関係にフォーカスします。
# 物体Aの運動と波及
## 運動の推定 三つ目の装置では、再びダイナミックな波を起こしていますが、波を起こす機構部は隠されています。 波の形をみただけで、波の原因となる機構が想像しやすいシンプルな形の波だけが見えることで、波という現象の裏には波を作る機構が必ず存在しているという因果関係を想像させています。
制作中
## 回転運動の影響 四つ目の装置には一見造波機構は見当たりません。装置を動かすとユニットそのものが回転し始め、波を生み出します。 なみなみユニットの中だけで完結していた事象を、ユニットという枠組みそのものを波を作る機構に取り込むことで作品のリフレーミングを促します。
@[twitter](https://x.com/AirpocketRobot/status/1986068043655721166) オープン型テストベッドで揺動機構の動作確認中
# メディアアートとしての「~~」 「~~」はなみの魅力を手軽に楽しむための卓上装置として制作しましたが、4つのユニットを連作として鑑賞することで# ~~
「~~(なみなみ)」は眺めているだけで心癒される。そして少し哲学的、科学的に思いを馳せることもできるかもしれない波を楽しむための装置です。
波動ジェネレータΨでの試験をもとに設計した揺動装置を使ってコンパクトなシリーズを制作しています。物体Aの運動と波及は横波発生機構を応用してダイナミックな波を生成します。
皆さんが波という言葉を聞いて連想するとき、そのイメージはポジティブな印象、例えば雄大な海の波を想起される方が多いのでh内科と思います。。
# 運動の推定
ゆったりと大きく力強い、時には繊細な波が繰り返し打ち寄せる。でもよくよく見ると二度と同じ波は来ない。 そんなイメージの波を卓上でお手軽に楽しんでみたいな。という思いから作った装置です。
縦波発生装置を使った 制作中
# 1/323,323
# ユニット交換式の卓上装置
開発中
@[youtube](]https://www.youtube.com/watch?v=jE8Rj6CCtNc)
@[twitter](https://x.com/AirpocketRobot/status/1986415884525764916) 疑似ランダム波の生成 7x11x13x17x19=323,323
「~~」は電子制御を行うコントローラ部、モーターによる駆動部を隠したドライバ、透明のケースの中に造波装置を埋め込んだなみなみユニットの三つの部位に分かれています。 なみなみユニットは現在4台が稼働しています。 ポンと乗せ換えるだけで交換できて、動力は磁力を介して伝達しています。
# ハードウェア構成図
# 回転運動の影響

開発中
メカの構成は上手の通りです。 SPRESENSEでステッピングモーターを制御し、ロータリーエンコーダーでモーターの回転数を変更できます。 SPRESENSEと拡張基板、DC-DC降圧ボードは3Dプリンタ製のベースボードの上に固定していますが、筐体のカバーは設置せず基板はむき出し。ディスプレイとロータリーエンコーダは固定せずケーブル接続しただけです。
# 回転運動の影響Ⅱ
ステッピングモーターは駆動部の筐体の中に隠し、外部からは見えないものの。なみなみユニットに動力を伝えていることは自明化と思います。
企画中
なみなみユニットは現在4種類をラインナップしています。駆動ユニットとは磁石で結合し、伝達された回転運動を種々の運動に変換して波を起こしています。
# 運動の推定Ⅱ
# なみなみユニット @[youtube](https://youtu.be/IVK1aeQ3ynU) なみなみユニットの動きは上の動画の通りです。
企画中
## 物体Aの運動と波及 一つ目の装置は、一目みただけで、波を作る機構部が波を起こす様子を理解できます。 ダイナミックかつシンプルな波です。 しかしながら細部を見ると同じ波は一つとして存在していないことにも気づきます。 シンプルなオブジェクトの動きが、シンプルさと複雑さの両方を引き起こす波の魅力の根幹を表しています
# 物体Aの運動と波及Ⅱ
## 1/323,323 二つ目の装置は、4枚のフィンの組み合わせがランダムな波を起こすことを狙っています。 フィンを駆動する歯車はそれぞれ異なる素数枚の歯をもっており、323,323回転に1回だけフィンが同期します。 シンプルな回転運動が静かではあるけれど複雑な状態を引き起こすという構造により、複雑な現象とメカ的な機構の関係にフォーカスします。
企画中
## 運動の推定 三つ目の装置では、再びダイナミックな波を起こしていますが、波を起こす機構部は隠されています。 波の形をみただけで、波の原因となる機構が想像しやすいシンプルな形の波だけが見えることで、波という現象の裏には波を作る機構が必ず存在しているという因果関係を想像させています。 ## 回転運動の影響 四つ目の装置には一見造波機構は見当たりません。装置を動かすとユニットそのものが回転し始め、波を生み出します。 なみなみユニットの中だけで完結していた事象を、ユニットという枠組みそのものを波を作る機構に取り込むことで作品のリフレーミングを促します。 # メディアアートとしての「~~」 「~~」は、波を眺めて楽しむための卓上装置として制作しました。しかし、4つのなみなみユニットを連作として鑑賞すると、この装置は単なる“癒やしのオブジェ”ではなく、波という現象そのものの成り立ちを考えさせるメディアとして立ち上がってきます。 私たちは普段、波を「結果」として見ています。 海の波、風に揺れる水面、音の波、光の波。 そこに必ず原因があることは知っていても、その仕組みを意識することはほとんどありません。 「~~」では、あえて波だけが目に入る構成をとっています。 なみなみユニットに近づくほど、内部の造波機構は隠され、観察者が直接見られるのは波の形とその変化だけです。一方で、電子制御部や配線、基板といった「本来は隠されがちな部分」はあえて露出させています。 この配置は偶然ではありません。 ## 見えないものが、現象を生む なみなみユニットの中で起きていることは、ほとんどの場合、外からは分かりません。 それでも確かに波は生まれ、揺れ、変化し続けます。 これは、海の波ととてもよく似ています。 海の波も、風や潮汐、地形といった複雑な要因によって生まれますが、私たちが目にするのはあくまで「波」という現象だけです。 「~~」は、この見えない因果関係と、見える現象の関係を、卓上サイズの装置で二重に表現しています。 なみなみユニットの内部に隠された物理的な造波機構 電子制御によってモーターを駆動し、その運動を生み出している制御系 どちらも直接は見えない、しかし確実に現象を支えている存在です。 ## ユニット交換という行為の意味 なみなみユニットは、ポンと乗せ換えるだけで交換できます。 操作としてはとても単純ですが、行っていることは少し変わっています。 ユニットを交換するという行為は、 波の見た目を変えているのではなく、波を生み出す因果関係そのものを差し替えているのです。 プログラムを書き換えているわけでも、数値パラメータを調整しているわけでもありません。 歯車の歯数、回転の位相、運動の変換方法といった、極めて物理的な構造そのものがユニットの中に封じ込められています。 その結果として現れる波は、同じ装置、同じ液体でありながら、まったく異なる性格を持ちます。 ## 波を「記録する」メディアとして この構造を考えているうちに、私はこの装置を波の記録メディアとして捉えるようになりました。 音楽を例にすると分かりやすいかもしれません。 カセットテープやレコードは、音そのものを直接扱うのではなく、音を生み出す情報や構造を物理的に記録しています。再生装置にかけることで、初めて音として立ち上がります。 なみなみユニットも、それとよく似ています。 ユニットの中に記録されているのは「波」ではない 記録されているのは「波を生み出す構造」 ユニットを交換すると、波が変わる。 それは、別の波を“再生”しているというより、別の因果関係を再生していると言った方が近いかもしれません。 デジタルでもなく、数値化もしていない。 非常に原始的で、完全にアナログな、波の記録装置です。 ## 卓上サイズの自然現象 「~~」は、海の波のスケールをそのまま再現しようとした装置ではありません。 むしろ、自然現象が持つ構造そのものを縮尺して持ち込むことを目指しています。 同じ条件でも二度と同じ波は現れないこと 単純な運動が、複雑な結果を生むこと 見えない構造が、確かに現象を支えていること それらを、静かに、しかし確実に感じ取れる卓上装置としてまとめました。 もし「~~」を前にして、 「なぜこの波が生まれているのだろう」 「中では何が起きているのだろう」 と少しでも想像してもらえたなら、この装置は役割を果たしていると思います。 波を眺めながら、原因に思いを巡らせる。 そんな時間を楽しんでもらえたら嬉しいです。 # コード ``` /* Copyright (c) 2019, miya Modified by airpocket, 2025 All rights reserved. (BSD 2-Clause License) */ #include <MediaPlayer.h> #include <OutputMixer.h> #include <MemoryUtil.h> #include <math.h> #include <Adafruit_GFX.h> #include <Adafruit_ILI9341.h> // ======= ILI9341 SPI接続ピン定義 ======= #define TFT_CS 10 // Chip Select #define TFT_DC 9 // Data/Command #define TFT_RST 8 // Reset(必要なければ省略可) Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); const int MIXER_VOLUME = -160; const int32_t S_BUFFER_SIZE = 8192; uint8_t s_buffer[S_BUFFER_SIZE]; bool err_flag = false; // ======= 波形パラメータ ======= const float SAMPLE_RATE = 48000.0f; float freq = 440.0f; // 初期周波数(Hz) int volume = 50; // 0〜100% int amplitude = 0; // 0〜32767 float phase = 0.0f; const float PI2 = 6.2831853f; // ======= Audio関連 ======= MediaPlayer *player; OutputMixer *mixer; // ======= 入力ピン設定 ======= const int POT_FREQ = A0; const int POT_VOL = A1; const float FREQ_MIN = 1.0f; const float FREQ_MAX = 1000.0f; const int ADC_FREQ_MIN = 30; const int ADC_FREQ_MAX = 610; const int ADC_VOL_MIN = 30; const int ADC_VOL_MAX = 610; // ======= コールバック ======= static void error_callback(const ErrorAttentionParam *errparam) { if (errparam->error_code > AS_ATTENTION_CODE_WARNING) { err_flag = true; } } static void mixer_done_callback(MsgQueId id, MsgType type, AsOutputMixDoneParam *param) { return; } static void mixer_send_callback(int32_t id, bool is_end) { AsRequestNextParam next; next.type = (!is_end) ? AsNextNormalRequest : AsNextStopResRequest; AS_RequestNextPlayerProcess(AS_PLAYER_ID_0, &next); return; } static bool player_done_callback(AsPlayerEvent event, uint32_t result, uint32_t sub_result) { return true; } // ======= 波形生成 ======= void generate_sine(int16_t *buf, uint32_t frames) { amplitude = (int)(32767.0f * (volume / 100.0f)); float phase_inc = PI2 * freq / SAMPLE_RATE; for (uint32_t i = 0; i < frames; i++) { int16_t v = (int16_t)(sin(phase) * amplitude); buf[i * 2 + 0] = v; buf[i * 2 + 1] = v; phase += phase_inc; if (phase >= PI2) phase -= PI2; } } // ======= PCMコールバック ======= void player_decode_callback(AsPcmDataParam pcm_param) { int16_t *buf = (int16_t*)pcm_param.mh.getPa(); uint32_t frames = pcm_param.size / 4; generate_sine(buf, frames); mixer->sendData(OutputMixer0, mixer_send_callback, pcm_param); } // ======= 初期化 ======= void setup() { Serial.begin(115200); // --- TFT 初期化 --- tft.begin(); tft.setRotation(1); // 横向き tft.fillScreen(ILI9341_BLACK); tft.setTextColor(ILI9341_WHITE); tft.setTextSize(2); tft.setCursor(20, 20); tft.println("Spresense Sine Generator"); tft.setTextSize(2); tft.setCursor(20, 50); tft.println("Initializing audio..."); // --- Audio初期化 --- initMemoryPools(); createStaticPools(MEM_LAYOUT_PLAYER); player = MediaPlayer::getInstance(); mixer = OutputMixer::getInstance(); player->begin(); mixer->activateBaseband(); player->create(MediaPlayer::Player0, error_callback); mixer->create(error_callback); player->activate(MediaPlayer::Player0, player_done_callback); mixer->activate(OutputMixer0, mixer_done_callback); usleep(100 * 1000); player->init(MediaPlayer::Player0, AS_CODECTYPE_WAV, "/mnt/sd0/BIN", AS_SAMPLINGRATE_48000, AS_BITLENGTH_16, AS_CHANNEL_STEREO); mixer->setVolume(MIXER_VOLUME, 0, 0); memset(s_buffer, 0, sizeof(s_buffer)); player->writeFrames(MediaPlayer::Player0, s_buffer, S_BUFFER_SIZE); player->start(MediaPlayer::Player0, player_decode_callback); tft.fillScreen(ILI9341_BLACK); Serial.println("[OK] Audio initialized."); } // ======= メインループ ======= void loop() { player->writeFrames(MediaPlayer::Player0, s_buffer, S_BUFFER_SIZE); // --- 周波数制御 --- int rawFreq = analogRead(POT_FREQ); if (rawFreq <= ADC_FREQ_MIN) freq = FREQ_MIN; else if (rawFreq >= ADC_FREQ_MAX) freq = FREQ_MAX; else freq = FREQ_MIN + (FREQ_MAX - FREQ_MIN) * ((float)(rawFreq - ADC_FREQ_MIN) / (ADC_FREQ_MAX - ADC_FREQ_MIN)); // --- ボリューム制御 --- int rawVol = analogRead(POT_VOL); if (rawVol <= ADC_VOL_MIN) volume = 0; else if (rawVol >= ADC_VOL_MAX) volume = 100; else volume = (int)(100.0f * (float)(rawVol - ADC_VOL_MIN) / (ADC_VOL_MAX - ADC_VOL_MIN)); // --- 表示更新 --- static unsigned long lastUpdate = 0; if (millis() - lastUpdate > 200) { lastUpdate = millis(); // シリアル出力 Serial.print("[A0]="); Serial.print(rawFreq); Serial.print(" [A1]="); Serial.print(rawVol); Serial.print(" -> [freq]="); Serial.print(freq, 1); Serial.print(" Hz [vol]="); Serial.print(volume); Serial.print("% [amp]="); Serial.println(amplitude); // TFT出力 tft.fillRect(0, 0, 320, 240, ILI9341_BLACK); tft.setCursor(20, 30); tft.setTextSize(2); tft.println("Spresense Sine Generator"); tft.setTextSize(2); tft.setCursor(20, 80); tft.printf("A0: %4d", rawFreq); tft.setCursor(20, 110); tft.printf("A1: %4d", rawVol); tft.setCursor(20, 150); tft.printf("Freq: %7.1f Hz", freq); tft.setCursor(20, 180); tft.printf("Vol: %3d %%", volume); tft.setCursor(20, 210); tft.printf("Amp: %5d", amplitude); } if (err_flag) { Serial.println("[ERROR] Audio system halted!"); tft.fillScreen(ILI9341_RED); tft.setCursor(20, 120); tft.setTextColor(ILI9341_WHITE); tft.setTextSize(2); tft.println("AUDIO SYSTEM HALTED"); player->stop(MediaPlayer::Player0); while (1); } usleep(1000); } ```