BingAIと作る M5stack core2 の時計(1)
BingAI に聞いてみた(第1回)
素人がスタックチャンに取り組む物語。
最近、BingAI というものが Edge に追加されました。話題の ChatGPT4 を利用しています。
プログラムの解析など得意だそうなので、素人が、マニュアルを見ながら、翻訳して考えるより、ずっと正確なのではないか、と思い、使ってみました。
諸先輩方には、簡単なことをお聞きするのは難しいですが、AIなら、簡単な、同じことを、何度聞いても気分を害されることはないし、時間を無駄にさせてしまうことも気にしなくていいので、気楽です。
ということで、現在取り組んでいる、robo8080さん作の「M5Unified‗StackChan」のプログラムを知るところから始めてみました。
GitHubのサイトを開いて、サイドバーからBingAIを立ち上げます。そうすると、現在のウェブページについて、BingAIとチャットしながらいろいろ聞けてしまいます。
下図は、独り言スタックチャンにボタンを押したらランダムに独り言を言う機能、をつけたくで、speachTask関数内がどうなっているのかBingAIに聞いた図です。

うん、素敵です!
「ボタンを押したときに再生するプログラムは?」と聞くと、簡単なサンプルプログラムを作ってくれたりします。今はChatGPTに利用の上限があるので難しいですが、プログラム全体を作ってくれる日も遠くないかもしれません。(2023/5/7時点)
ちょっと色々聞きながら、目標とする改造を達成していきたいです。
追記
長いですが、以下、BingAIとの会話履歴です。私のプログラム能力がばれてしまう会話内容です。最後にBingAIにお腹いっぱいなので話題を変えてください、と言われました。たぶん、怒ってはいないはず。。。
ープログラムの概略を教えてください
現在のウェブページのコンテキストによると、このプログラムは、M5Stack デバイスで音声ファイルを再生するためのものです。プログラムは、SD カードから音声ファイルを読み込み、M5Stack のスピーカーを使用して再生します。また、プログラムには、サーボモーターを制御する機能も含まれています。さらに、リップシンク機能も実装されており、音声再生中に口の開き具合が調整されます。
ー再生するタイミングはどのコマンドで調整されていますか?
現在のウェブページのコンテキストによると、speachTask 関数内で、vTaskDelay(2000 + 1500 * random(20)); という行があります。この行は、音声再生のタイミングを調整するために使用されているようです。この行は、音声再生が終了した後、次の音声再生までの待機時間をランダムに設定しています。
ーそのタイミングに加えて、ボタンを押したタイミングで再生するようにするためには、どのようなコメントを加えたらよいでしょうか?具体的に。
M5Stack デバイスには、3つのボタンがあります。ボタンA、ボタンB、ボタンCです。これらのボタンのいずれかを押したときに音声ファイルを再生するようにするには、loop() 関数内に次のようなコードを追加することができます。
void loop() {
if (M5.BtnA.wasPressed()) {
// ボタンAが押されたときの処理
play(fileList[0].c_str()); // 最初の音声ファイルを再生
}
if (M5.BtnB.wasPressed()) {
// ボタンBが押されたときの処理
play(fileList[1].c_str()); // 2番目の音声ファイルを再生
}
if (M5.BtnC.wasPressed()) {
// ボタンCが押されたときの処理
play(fileList[2].c_str()); // 3番目の音声ファイルを再生
}
delay(100);
}
上記のコードでは、ボタンA、ボタンB、ボタンCが押されたときに、それぞれ異なる音声ファイルが再生されるようになっています。もちろん、このコードはあくまでも例ですので、実際に使用する際には、必要に応じて変更してください。
ーボタンを押したときにランダムに再生するにはどのようにしたらよいですか?
M5Stack デバイスのボタンを押したときに、ランダムに音声ファイルを再生するようにするには、loop() 関数内に次のようなコードを追加することができます。
void loop() {
if (M5.BtnA.wasPressed()) {
// ボタンAが押されたときの処理
int index = random(0, fileCount); // ランダムなインデックスを生成
play(fileList[index].c_str()); // ランダムな音声ファイルを再生
}
delay(100);
}
上記のコードでは、ボタンAが押されたときに、fileList 配列内の音声ファイルがランダムに選択され、再生されるようになっています。もちろん、このコードはあくまでも例ですので、実際に使用する際には、必要に応じて変更してください。
ー現在のウエブで、ランダムな再生はどのように表わされていますか?
申し訳ありませんが、現在のウェブページのコンテキストには、ランダムな再生に関する情報はありません。
ーspeachTask関数内で、ランダムに再生するコマンドがありませんか?
はい、speachTask 関数内には、ランダムに音声ファイルを再生するコマンドがあります。現在のウェブページのコンテキストによると、speachTask 関数内に次のような行があります。
data_index = random(0, fileCount);
play(fileList[data_index].c_str());
この行は、fileList 配列内の音声ファイルをランダムに選択し、再生するために使用されています。
ーspeachTask 関数内の処理についてもう少し詳しく解説してください。
現在のウェブページのコンテキストによると、speachTask 関数は、音声ファイルの再生を制御するためのものです。この関数は、無限ループ内で実行されます。ループ内では、まず wav.isRunning() 関数が呼び出され、音声再生が実行中かどうかが確認されます。音声再生が実行中でない場合、data_index 変数にランダムな値が設定され、fileList[data_index].c_str() で指定された音声ファイルが再生されます。その後、vTaskDelay(2000 + 1500 * random(20)); 関数が呼び出され、次の音声再生までの待機時間が設定されます。
この関数は、音声ファイルをランダムに選択し、一定時間ごとに再生するために使用されています。
ーspeachTask 関数内で無限ループしていると、ボタン押したときに再生するコメントをvoid loop内に記述しても実行されないのでは?
speachTask 関数は、別のタスクとして実行されます。この関数内で無限ループが実行されていても、loop() 関数内の処理は実行されます。つまり、loop() 関数内にボタンが押されたときの処理を記述しておけば、その処理は実行されます。
ただし、speachTask 関数内で音声再生が実行中の場合、loop() 関数内でボタンが押されたときに音声再生を開始する処理が実行されても、その音声再生は実行されません。これは、play() 関数内で、音声再生が実行中かどうかが確認され、実行中の場合は新しい音声再生が開始されないようになっているためです。
したがって、speachTask 関数内で無限ループが実行されていても、loop() 関数内に記述された処理は実行されますが、その処理が正しく動作するかどうかは、プログラムの詳細な構造に依存します。
ーplay() 関数内の処理について教えてください
現在のウェブページのコンテキストによると、play() 関数は、音声ファイルを再生するためのものです。この関数は、引数として音声ファイルのファイル名を受け取ります。
関数内では、まず file 変数が nullptr でないかどうかが確認されます。file 変数が nullptr でない場合、stop() 関数が呼び出され、現在実行中の音声再生が停止されます。
次に、file 変数に新しい AudioFileSourceSD オブジェクトが作成され、引数で指定された音声ファイルが開かれます。その後、buff 変数に新しい AudioFileSourceBuffer オブジェクトが作成されます。
最後に、wav.begin(buff, &out); 関数が呼び出され、音声再生が開始されます。その後、wav.isRunning() 関数が呼び出され、音声再生が実行中かどうかが確認されます。音声再生が実行中の場合、wav.loop() 関数が呼び出され、音声データの処理が行われます。この処理は、音声再生が終了するまで繰り返されます。
この関数は、指定された音声ファイルを再生するために使用されます。
ーnullptrとはなに?
nullptr は、C++11 以降の C++ 言語において、ポインタ型の変数が何も指していないことを表すために使用される特殊な定数です。nullptr は、従来の C 言語における NULL 定数と同様の役割を果たしますが、より厳密な型チェックが行われるため、より安全に使用することができます。
例えば、次のようなコードがあります。
int *p = nullptr;
このコードでは、p という名前のポインタ型変数が宣言され、その値が nullptr に設定されています。これは、p 変数が現在何も指していないことを表しています。
ポインタ型変数が nullptr であるかどうかを確認することで、その変数が有効な値を指しているかどうかを判断することができます。
ー「その後、wav.isRunning() 関数が呼び出され、音声再生が実行中かどうかが確認されます。音声再生が実行中の場合、wav.loop() 関数が呼び出され、音声データの処理が行われます。この処理は、音声再生が終了するまで繰り返されます。」という処理はどうして必要?
wav.isRunning() 関数は、音声再生が実行中かどうかを確認するために使用されます。この関数が true を返す場合、音声再生が実行中であることを示します。
wav.loop() 関数は、音声データの処理を行うために使用されます。この関数は、音声データをデコードし、オーディオ出力デバイスに送信するためのものです。この関数は、音声再生が終了するまで繰り返し呼び出される必要があります。
これらの処理は、音声再生を正しく行うために必要です。wav.isRunning() 関数が true を返す間、wav.loop() 関数を繰り返し呼び出すことで、音声データが正しく処理され、オーディオ出力デバイスに送信されます。
ーwav.loop() 関数を繰り返し呼び出さないと、再生の途中で止まる?
はい、その通りです。wav.loop() 関数は、音声データの処理を行うために使用されます。この関数が繰り返し呼び出されない場合、音声データの処理が停止し、音声再生が途中で止まる可能性があります。
wav.loop() 関数は、音声データをデコードし、オーディオ出力デバイスに送信するためのものです。この関数が繰り返し呼び出されることで、音声データが正しく処理され、オーディオ出力デバイスに送信されます。したがって、この関数を繰り返し呼び出さないと、音声再生が途中で止まる可能性があります。
ーwav.loop() 関数はどうやって音声を再生しているの?
wav.loop() 関数は、音声データの処理を行うために使用されます。この関数は、音声データをデコードし、オーディオ出力デバイスに送信するためのものです。
具体的には、wav.loop() 関数は、次のような処理を行います。
- 音声ファイルから音声データを読み込みます。
- 読み込んだ音声データをデコードします。
- デコードされた音声データをオーディオ出力デバイスに送信します。
この関数が繰り返し呼び出されることで、音声データが正しく処理され、オーディオ出力デバイスに送信されます。その結果、音声が再生されます。
ただし、wav.loop() 関数自体は、直接的に音声を再生するものではありません。この関数は、音声データの処理を行い、オーディオ出力デバイスに送信することで、間接的に音声再生を実現しています。
ーwav.loop() 関数はこのプログラムに無いようだけど?
はい、その通りです。wav.loop() 関数は、このプログラム内には定義されていません。この関数は、AudioGeneratorWAV クラスのメンバ関数です。このクラスは、外部ライブラリに定義されており、このプログラム内で使用されています。
このプログラム内では、wav という名前の AudioGeneratorWAV クラスのオブジェクトが作成されており、そのメンバ関数である loop() 関数が呼び出されています。この関数は、音声データの処理を行うために使用されます。
ー他のプログラムに記述されているAudioGeneratorWAV クラスの、wav という名前のオブジェクトの、メンバ関数である loop() 関数を使っている、ということ?
はい、その通りです。wav.loop() 関数は、AudioGeneratorWAV クラスのメンバ関数です。このクラスは、外部ライブラリに定義されており、このプログラム内で使用されています。
このプログラム内では、wav という名前の AudioGeneratorWAV クラスのオブジェクトが作成されており、そのメンバ関数である loop() 関数が呼び出されています。この関数は、音声データの処理を行うために使用されます。
つまり、このプログラムは、外部ライブラリに定義されている AudioGeneratorWAV クラスの wav という名前のオブジェクトを使用しており、そのメンバ関数である loop() 関数を呼び出しています。
ー「wav.loop() 関数は、次のような処理を行います。 音声ファイルから音声データを読み込みます。 読み込んだ音声データをデコードします。 デコードされた音声データをオーディオ出力デバイスに送信します。 この関数が繰り返し呼び出されることで、音声データが正しく処理され、オーディオ出力デバイスに送信されます。その結果、音声が再生されます。」という説明から考えると、wav.loop() 関数は音声データを部分的に切り取って順番に出コードしているから、関数を繰り返し実行する必要があるのかな、と考えますが、あっていますか?
はい、その通りです。wav.loop() 関数は、音声データを部分的に切り取って順番にデコードし、オーディオ出力デバイスに送信するために使用されます。この関数が繰り返し呼び出されることで、音声データが正しく処理され、オーディオ出力デバイスに送信されます。
音声ファイルは、通常、長い音声データを含んでいます。この音声データを一度にすべて処理することは困難です。そのため、wav.loop() 関数では、音声データを部分的に切り取って順番に処理することで、音声再生を実現しています。
この関数が繰り返し呼び出されることで、音声データが順番に処理され、オーディオ出力デバイスに送信されます。その結果、音声が再生されます。
ーどの位の大きさに切り取っているの?全体としてはどのくらいの大きさの音声ファイルまで扱えるの?
wav.loop() 関数が処理する音声データのサイズは、このプログラム内では明示的に指定されていません。このサイズは、AudioGeneratorWAV クラスの内部実装に依存します。
一般的に、AudioGeneratorWAV クラスは、音声データをバッファリングして処理するため、処理する音声データのサイズは、バッファのサイズに依存します。バッファのサイズは、AudioGeneratorWAV クラスの内部実装によって異なりますが、通常は数キロバイトから数十キロバイト程度です。
AudioGeneratorWAV クラスは、大きな音声ファイルでも扱うことができます。このクラスは、音声データを部分的に切り取って順番に処理するため、音声ファイルのサイズが大きくても問題ありません。ただし、音声ファイルが非常に大きい場合、処理に時間がかかる可能性があります。
ー音声データをバッファリングして処理する、とはどういうこと?
音声データのバッファリングとは、音声データを一時的にメモリ上に保存しておき、そのデータを順次処理することを指します。このような処理は、音声再生において一般的に使用されます。
音声ファイルは、通常、長い音声データを含んでいます。この音声データを一度にすべて処理することは困難です。そのため、音声再生プログラムでは、音声データを部分的に切り取って順番に処理することが一般的です。
このような処理を実現するために、音声再生プログラムでは、バッファと呼ばれるメモリ領域が使用されます。バッファは、音声データを一時的に保存するためのものです。音声再生プログラムは、音声ファイルから音声データを読み込み、そのデータをバッファに保存します。その後、バッファ内のデータが順次処理され、オーディオ出力デバイスに送信されます。
このような処理により、音声再生プログラムは、長い音声データを効率的に処理することができます。
。。。。
このあと、以下のようにBingAIに言われました。
「Unfortunately, we need to move on! Click “New topic” to chat more.」
怒ってないよね。容量がいっぱいになっただけだよね。人間はそういう時、怒るけど。
BingAIさん、話の続きはまた今度よろしくお願いいたします。
PlatformIO ― platform.ini について
PlatformIO ― platform.ini について
「 env: 」、「 platform 」、「 framework 」、「 board 」 編
以下の記事はPlatformIO ホームページを参考にしています。
“ PlatformIO は 「platform.ini」 (プロジェクト設定ファイル)で各プロジェクトごとに環境設定をします。 このファイルの記述に基づいて、PlatformIOは必要なツールチェーンを自動的にダウンロードし、インストールします。そして、設定に記述されたボード型にコンパイルやアップロードを行います。 ”
素人的理解では、、、
PlatformIOで
新規にプロジェクトを立ち上げた時
Gitからリポジトリをクローンしてプロジェクトを立ち上げた時
編集中のプロジェクトでも 「platform.ini」 を書き換えて保存した時
右下にコメントがでて何か作業してくれています。それが、「platform.ini」ファイルを基に、環境を設定している、ということかな、と。初回は結構時間がかかります。
自動でやってくれるのは大変ありがたいですが、一度つまづくと素人では立て直すことが大変難しいところでもあります。(たぶん後で出てくるバージョン指定の問題が大きいかと愚考)
難しい ( ^ω^)・・・
どんな設定が書いてあるのか理解するために、まず、「PlatformIO ホームページ platform.ini について」から「 .iniファフィル の記述の仕方」についての例をみてみましょう。
(https://docs.platformio.org/en/latest/projectconf/index.html#projectconf)

VScodeなどで「platform.ini」ファイルを開くと上図のような記述があります。
[ ] (大かっこ) +env で 各プロジェクト全体の環境設定
[ ] (大かっこ) +env:プロジェクト名(任意につけることができる)で各プロジェクト内での個別の環境設定
をしているのだと思います。任意につけることができますが、後で見てわかりやすい名前がいいです。
[env]又は[env:プロジェクト名] 以下の
platform =
framework =
board =
と
lib_deps =
が大事なところかな、と思います。ライブラリ関係は情報が多いので、別にページを作ります。
build_flags =
もよく見かけるので大切そうですが、今の私にはまだ理解できません。また、そのうちに、、、
メモ platform.ini での記述の決まりについて
「;」で始まる行は無視され、コメントの入力に使用できます。
複数の値を指定するには、次の 2 つの方法があります。
1)値を ", " (コンマ + スペース) で分割します。(半角スペースなのでわかりにくい!)
例) default_envs = uno, nodemcu (nodemcuの前に半角スペースがあります!)
2)複数行形式。新しい行はそれぞれ少なくとも 2 つ以上のスペースで始まります。
(上図の中の 「 lib_deps = 」以降の記述を参考にしてみてください。)
それでは[env:プロジェクト名]以下の「 platform 」、「 framework 」、「 board 」についてみていきます。私がよく使っているM5stackを例に調べてみます。「 platform 」、「 framework 」、「 board 」の細かい定義はホームページをみてもよくわかりません。
M5stack だと
platform は espressif32 (M5stack社製品ですが、心臓部はespressif社のESP32を使っています。)
framework は arduino (ここはよくわかりません。)
board は m5stack-core2 (製品名です。)
後で述べますが、ここの記述はPlatformIOのRegistry(レジストリ)に登録されているものと一致する必要があります。
になります。
「 platform 」、「 framework 」、「 board 」は任意に名前を付けることはできません。既定の名前とバージョンがあります。それらはPlatformIO ホームページのRegistry(レジストリ)から検索できます。(恐らく、諸々自分で作り上げる力があれば、任意の名前を付けることができますが。)


「ESP32」で検索すると公式のPlatform一式がでてきます。


platform 2023/4/19時点の最新バージョンは6.1.0ですが、画面右下の方から過去のバージョンも選択できます。
Boards 197個が登録されている。(2023/4/19時点)
Frameworks 「Arduino」「Espidf」の二つ
ここに登録された「 platform」、「 framework 」、「 board 」が利用できる「名称」です。
arduinoで作られた「.ino」ファイルを使う時は、FrameworkにAruduinoを指定する必要がありそうです。<Aruduino.h>を自動でインストールしてくれる、のかな?
さらに、この画面右下の方に、Dependencies17 として依存関係のあるファイルたちが記載されています。このファイル間の依存関係を自動で調べて、ライブラリやコンパイルなどのプログラムをまとめてくれるのがPlatformIOの本業なのかな、と思います。
この時に、参照するプログラムのバージョンを指定することで、将来の予期せぬバージョン変更に伴う、危機的なエラーを回避することができます。バージョンを指定しておかないと、常に最新バージョンを参照するので、本プログラムもその度に調整する必要がでてきます。
Installationをみると、この platform を platform.ini に導入する方法が書いてあります。
Command Line Interface(CLI)は、私、使い慣れないので省略します。英語が読める方は自分で読んでいただいた方が確かだと思います。(私は、英語力も、プログラム力も危うい、、、)
推奨される記述の仕方
(バージョンの部分指定)
platform = espressif32@^3.5.0
(バージョンの部分指定)
platform = espressif32@~3.5.0(注:チルダです、詳細後述)
(バージョンを固定) 多分、最も推奨される方法
platform = espressif32@3.5.0
推奨されない記述の仕方
(常に最新版を導入)
platform = espressif32 (@以降がない)
gitのアドレスからの指定 (多分、gitのバージョンまで指定できそうです。)
(開発版) (これは、常に最新版をインストールすることになるのかな?)
platform = https://github.com/platformio/platform-espressif32.git
ちょっとここから先は未理解です。
(gitのブランチを指定?)
https://github.com/platformio/platform-espressif32.git#master
(gitの特定のバージョンを指定?)
https://github.com/platformio/platform-espressif32.git#f8340a2081a31c2ac8ed2b16907f2a21dc8897d4
さて、いくつかのエラーを経て得た素人的理解では、バージョン指定をするのがもっともよさそうです。公式ホームページでもそう記載されています。(当然ですが、、、)バージョン違いによるエラーはエラーメッセージからは理解しにくいです。エラーでは「ファイルが無い」「ビルドできない」「コンパイルできない」という形で表現されるからです。
メモ2 PlatformIOでの
バージョンの記述のルール
(https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_install.html#version-requirements)
PlatformIO は Python セマンティックバージョンに基づいている、らしいです。PlatformIO自体がPythonで作られているから、まあ、そうでしょう。
ファイル名の語尾に
@<バージョン要件><MAJOR>.<MINOR>.<PATCH>
<MAJOR> ファイルの大きな変更。互換性がなくなる。
<MINOR> 機能の追加(下位互換性)。
<PATCH> バグ修正(下位互換性)。
<バージョン要件>
まず簡単に、よくわからない記号について。
(̂:サーカムフレックス。キャレット記号に似ているのでキャレット記号と呼ばれることもある)
(~はチルダ(半角)で、行の上部に表示されるものです。技術不足のためHP上に表示できませんでした。すいません。)
^1.2.3- 1文字目だけ指定(下位互換性のある機能、1.x.xということ。)
~1.2.3- 1文字目と2文字目が同じバージョン、及び同等以上の3文字目バージョン
1.2.3- 正確なバージョン番号。バージョン要件は空白(半角)。
他にも色々なバージョン指定の書式がありますが、よくわからないのでここでは省略します。
「 framework 」、「 board 」も同様に、PlatformIO ホームページのRegistry(レジストリ)から検索できます。Explore で登録された「 Library」 「 Platform」 「 Tool」 を検索することができます。

実際のところ、これらのファイルの中身がなにで、何が必要なのか、は私にはまだわかりませんが、PlatformIO は 「platform.ini」 (プロジェクト設定ファイル)で各プロジェクトごとに環境設定をする時に、「platform.ini」の記述に基づいて、このレジストリや、PCに作られたPlatformIO用のローカルのレジストリを参照して、必要なバージョンのツールファイルやライブラリやコンパイルソフトなどを自動的にダウンロードし、インストールしてくれているのだと思います。
「 platform 」、「 framework 」、「 board 」についての記事でした。
PlatformIOはいろいろなプログラム開発環境を自動で統合してくれますが、その肝は「 platform.ini」 (プロジェクト設定ファイル)にあるのだと思います。PlatformIOはプロジェクトを作成した時に、メインのプログラムをとりまくプログラムとその依存関係を、指定したバージョンで、環境構築し保存するので、参照先のライブラリが変更されても影響を受けなくすることができます。C言語系なら、プリプロセス、コンパイル、アセンブル、リンクして実行ファイルの作成までできる環境構築を自動でしてくれます。
今回参照した主なページです。
PlatformIO 最新のドキュメント フロントページ
https://docs.platformio.org/en/latest/
「platformio.ini」 (Project Configuration File)についてのページ https://docs.platformio.org/en/latest/projectconf/index.html
「platforms」の最新のドキュメント
https://docs.platformio.org/en/latest/platforms/index.html
「frameworks」の最新のドキュメント
https://docs.platformio.org/en/latest/frameworks/index.html
「boards」の最新のドキュメント
https://docs.platformio.org/en/latest/boards/index.html
PlatformIO 「Registry」 実際のファイルのあるところ
https://registry.platformio.org/search
今後も理解を深めていきたいです。
VScode完全アンインストール
最初に注意点です
この記事を書いている私は、熟練プログラマーではありません。趣味で電子工作やプログラムを始めて1年ほどの人間です。その過程で、学習した、経験した、実践した、ものを記しています。基本的に検索して得た情報を私なりに解釈し、まとめたものです。
それぞれのパソコンの環境によって必要な情報、操作は異なるはずです。
ご注意ください。
私の作業環境です。( 2023年4月12日 時点)
Windows11
VScode バージョン: 1.77.3
VScode完全アンインストール
(Microsoft Visual Studio Code 以下VScodeと略します。)
まず、ざっくりと、説明します。後ですこし細かく説明します。
以下の3つが必要です。
①Windowsの機能から「Microsoft Visual Studio Code」を アンインストール する。
② 例)C:\Users\ユーザ名\.vscode のフォルダを削除する。
③ 例)C:\Users\ユーザ名\AppData\Roaming\Code のフォルダを削除する。
すこし細かく説明します。
厄介なことに、VScodeは、通常のアンインストールを行ってもいくつかの設定やファイルは残るようです。それによって、再インストールしても前回の設定が知らないうちに反映されていたりします。そしてエラーが繰り返されます。それを避けるために、残っている設定のファイルなどを削除します。
知識があれば、その設定ファイルを直接書き換えるとよいのだと思いますが、今はまだ私にはその技術はありません。
完全に削除するには3つの作業が必要です。
① Windows の機能から「Microsoft Visual Studio Code」を アンインストール する。
いつもの、普通の、通常の、アンインストールです。

② 例)C:\Users\ユーザ名\.vscode のフォルダを削除する。
VScodeの機能拡張関連のファイルは、Windowsユーザフォルダ内の 「.vscode」 フォルダにあります。「ユーザー名」は、例えば 「山田太郎」、「taroyamada」などになっていると思います。エクスプローラーで探して、右クリックなどで「.vscode」フォルダごと削除してください。別の場所にコピーしておいてもよいかと思います。

③ 例)C:\Users\ユーザ名\AppData\Roaming\Code のフォルダを削除する。
settings.jsonなどのユーザ設定ファイル等は、隠しフォルダである AppData フォルダ内のRoming フォルダ内のCodeフォルダ にあります。
エクスプローラーで「隠しフォルダ」を表示する方法は、、、、「隠しフォルダ」「表示」で検索してみてください。個々の環境によって画面に違いがあるようです。エクスプローラー上部の「表示」の中に「隠しファイルの表示/非表示」を選択するところがあると思います。
「隠しファイル」を「表示」すると、若干薄い色で隠されていたフォルダやファイルが表示されます。
C:\Users\ユーザ名\AppData\Roaming\Code のフォルダを、右クリックなどで「Code」フォルダごと削除してください。別の場所にコピーしておいてもよいかと思います。

これで VScode は完全にアンインストールされました。
メモ
「AppData」フォルダについて
AppDataは、特定のアプリケーションの設定またはカスタマイズオプションに関する「ユーザーごと」の情報を記録しておくところです。
通常アプリケーションの本体は「C:\Program Files」または「C:\Program Files(x86)」といった「C:\」に配置され、マシン上の「全てのユーザー」に対してサービスを提供します。アプリケーション設定も、「全てのユーザー」に伝達されます。
AppDataフォルダーを持つことの利点は、1つのシステムに複数のユーザーがいる場合です。AppDataを利用することで、「ユーザーごと」のアプリケーションの設定が可能になります。
「C:\」へのアクセスには管理者権限が必要ですが、AppDataは管理者権限を必要としません。
メモ2
プログラムの本体をどこに置くのか、ということは長年議論されている問題だそうです。「C:\Program Files」はパスに空白を含むことが問題のようです。空白や0(ゼロ)の扱いが、プログラム言語によって異なることに起因するようです。WindowsにPythonをインストールすると、デフォルトのインストール先はユーザーディレクトリ内の AppData\Local¥Programs¥Python になるそうです。
詳細は検索してください。私には理解できないことを多く含んでいます。
メモ3
ディレクトリーのセパレーター(区切り記号)とは、インターネットのURL区切り記号で「/(スラッシュ)」に対応する文字のことです。Linuxの場合は、インターネットのURLと同じく「/(スラッシュ)」が使われるのですが、Windowsの場合は、「\(バックスラッシュ)」が使われます。さらに日本語フォントの場合は、「\」と「¥」のキーコードが同じため「¥」になっていることがほとんどです。「ファイルが見つからない」などのエラーの場合はセパレーターをチェックするのが良いかもしれません。「/(全角)」「/(半角)」もあるのでさらにややこしいです。詳細は検索してみてください。歴史的経緯からも根が深そうです。
ブログ開設
M5stackでスタックチャンというものを作りました。
作ったといっても、M5stack core 2 を スイッチサイエンス さんで購入し、諸先輩方の開発したプログラムを導入したものです。
これから M5stack 及び スタックチャン にまつわる記事を書いていきたいです。