Pythonのリスト内包表記をマスターしよう
はじめに
Pythonを学んでいる多くの方が、最初はforループを使ってリストを作成しますが、Pythonにはもっとエレガントで効率的な方法があります。それがリスト内包表記(List Comprehension)です。
この記事では、リスト内包表記の基本から応用まで、実例を通じて解説します。
リスト内包表記とは?
リスト内包表記は、既存のリストやイテラブルから新しいリストを簡潔に作成するPythonの構文です。forループを使った従来の方法と比べて、コードが短く、読みやすく、実行速度も速いという特徴があります。
基本的な使い方
従来の方法 vs リスト内包表記
まず、従来のforループを使った方法を見てみましょう:
# 従来の方法 numbers = [] for i in range(1, 11): numbers.append(i * 2) print(numbers) # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
これをリスト内包表記で書き直すと:
# リスト内包表記 numbers = [i * 2 for i in range(1, 11)] print(numbers) # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
たった1行で同じ結果が得られます!
構文の基本パターン
リスト内包表記の基本構文は以下の通りです:
[式 for 要素 in イテラブル]
例1: 数値のリストを作成
# 1から10までの平方数を生成 squares = [x**2 for x in range(1, 11)] print(squares) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
例2: 文字列の変換
# 文字列リストを大文字に変換 words = ["hello", "world", "python"] upper_words = [word.upper() for word in words] print(upper_words) # ['HELLO', 'WORLD', 'PYTHON']
条件付きリスト内包表記
条件を追加することで、特定の条件を満たす要素だけを含むリストを作成できます。
ifを使ったフィルタリング
# 偶数のみを抽出 numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] even_numbers = [x for x in numbers if x % 2 == 0] print(even_numbers) # [2, 4, 6, 8, 10]
if-elseを使った条件分岐
# 偶数なら2倍、奇数なら3倍にする numbers = [1, 2, 3, 4, 5] result = [x * 2 if x % 2 == 0 else x * 3 for x in numbers] print(result) # [3, 4, 9, 8, 15]
ネストしたリスト内包表記
リスト内包表記はネストさせることもできます。
# 2次元のリストを作成(九九の表) multiplication_table = [[i * j for j in range(1, 10)] for i in range(1, 10)] print(multiplication_table[0]) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
ただし、ネストが深くなりすぎると読みづらくなるので、3重以上のネストは避けた方が良いでしょう。
実践的な例
例1: ファイル名の拡張子を変更
# .txtファイルの拡張子を.mdに変更 txt_files = ["readme.txt", "guide.txt", "notes.txt"] md_files = [file.replace(".txt", ".md") for file in txt_files] print(md_files) # ['readme.md', 'guide.md', 'notes.md']
例2: データのフィルタリングと変換
# 商品価格から税込み価格を計算(1000円以上の商品のみ) prices = [800, 1200, 1500, 600, 2000] taxed_prices = [int(price * 1.1) for price in prices if price >= 1000] print(taxed_prices) # [1320, 1650, 2200]
例3: 文字列の処理
# 文章から単語を抽出し、3文字以上の単語のみを取得 sentence = "The quick brown fox jumps over the lazy dog" long_words = [word for word in sentence.split() if len(word) >= 4] print(long_words) # ['quick', 'brown', 'jumps', 'over', 'lazy']
注意点とベストプラクティス
1. 読みやすさを優先する
リスト内包表記は便利ですが、複雑になりすぎると可読性が下がります。以下のような場合は、通常のforループの方が良いかもしれません:
# 複雑すぎる例(推奨しない) result = [x * 2 if x % 2 == 0 else x * 3 if x > 5 else x for x in range(10) if x % 3 != 0]
2. メモリ効率
リスト内包表記は一度にすべての要素をメモリに保持します。大量のデータを処理する場合は、ジェネレータ式を使うことを検討しましょう:
# ジェネレータ式(メモリ効率が良い) large_numbers = (x**2 for x in range(1000000))
3. パフォーマンス
リスト内包表記は通常のforループよりも高速ですが、その差は微々たるものです。可読性と使いやすさを優先しましょう。
まとめ
リスト内包表記は、Pythonの強力な機能の一つです。適切に使えば、コードをより簡潔で読みやすく、効率的にすることができます。ただし、複雑になりすぎないよう注意が必要です。
SQL入門
はじめてのSQL入門 ― ITエンジニアなら押さえておきたいデータベースの基本
アプリ開発でも業務システムでも、「データをどこにどう保存するか」は必ず出てくるテーマです。
そこで登場するのが RDB(リレーショナルデータベース) と、それを操作するための言語 SQL(エスキューエル / シークェル) です。
この記事では、これからITエンジニアを目指す人向けに、SQLの超基本をまとめます。
SQLって何をするもの?
SQL(Structured Query Language) は、データベースに対して
- データを登録する(INSERT)
- データを取り出す(SELECT)
- データを更新する(UPDATE)
- データを削除する(DELETE)
といった操作を行うための言語です。
RDBには、代表的なものとして
- MySQL / MariaDB
- PostgreSQL
- SQLite
- SQL Server
- Oracle Database
などがありますが、基本的なSQL文はどれもかなり共通しています。
テーブルとレコードのイメージ
RDBでは、データは表(テーブル)の形で管理されます。
- テーブル: Excelのシートのようなもの
- 行(レコード): 1件分のデータ
- 列(カラム): データの項目(名前、メールアドレス、年齢など)
例として、users というテーブルを考えてみます。
| id | name | age | |
|---|---|---|---|
| 1 | Taro | taro@example.com | 25 |
| 2 | Hanako | hanako@example.com | 30 |
この users テーブルに対して、SQLでいろいろな操作をしていきます。
データを取り出す (SELECT)
まずは一番よく使う SELECT文 から。
すべてのデータを取得
SELECT * FROM users;- SELECT * : すべてのカラムを取り出す
- FROM users : users テーブルから
特定のカラムだけ取得
SELECT name, email FROM users;### 条件をつけて取得 (WHERE)
SELECT * FROM users
WHERE age >= 30;
SELECT * FROM users
WHERE name = 'Taro';- WHERE で絞り込み条件を指定します。
- 文字列は '...' で囲みます。
並び順を指定 (ORDER BY)
SELECT * FROM users
ORDER BY age DESC;- ORDER BY age DESC : 年齢の高い順(降順)
- 逆に小さい順(昇順)は ASC(省略可)
データを追加する (INSERT)
新しいユーザーを追加したいときは INSERT文 を使います。
INSERT INTO users (name, email, age)
VALUES ('Jiro', 'jiro@example.com', 20);- INSERT INTO users (カラム名...)
- VALUES (値...) : カラムの順番と合わせる
データを更新する (UPDATE)
既存データを変更したいときは UPDATE文 です。
UPDATE users
SET age = 26
WHERE id = 1;- SET で変更するカラムと値を指定
- WHERE をつけないと全行が更新されるので注意
複数カラムをまとめて更新することもできます。
UPDATE users SET name = 'Taro Yamada', email = 'taro.yamada@example.com' WHERE id = 1;---
データを削除する (DELETE)
不要になったデータを消すには DELETE文 です。
DELETE FROM users
WHERE id = 2;これも、WHERE をつけないとテーブルの全データが消えるので要注意です。
条件指定のバリエーション
WHERE 句では、いろいろな条件が書けます。
比較演算子
SELECT * FROM users WHERE age > 20; SELECT * FROM users WHERE age <= 30; SELECT * FROM users WHERE age <> 25; -- 25ではない### 複数条件の組み合わせ (AND / OR)
SELECT * FROM users WHERE age >= 20 AND age <= 30;
SELECT * FROM users WHERE name = 'Taro' OR name = 'Hanako';### 曖昧検索 (LIKE)
SELECT * FROM users
WHERE email LIKE '%@example.com';- % は「任意の文字列」のワイルドカード
'%@example.com' は「@example.com で終わるメールアドレス」という意味
集計してみる (COUNT / MAX / MIN / AVG / SUM)
簡単な統計もSQLでできます。
-- ユーザー数を数える SELECT COUNT(*) FROM users;
-- 最大年齢・最小年齢 SELECT MAX(age) AS max_age, MIN(age) AS min_age FROM users;
-- 平均年齢
SELECT AVG(age) AS avg_age FROM users;- AS 別名 でカラム名のようなラベルを付けられます。
グループごとに集計 (GROUP BY)
例えば「年齢ごとに何人いるか」を知りたいとき。
SELECT age, COUNT(*) AS count FROM users GROUP BY age;結果イメージ:
| age | count |
|---|---|
| 20 | 3 |
| 25 | 1 |
| 30 | 2 |
テーブル同士をつなぐ (JOIN) のイメージ
RDBの真骨頂は、テーブルを分けて正規化し、それをJOINでつなぐことです。
例として、
usersテーブル(ユーザー情報)ordersテーブル(注文情報)
があるとします。
SELECT
users.name,
orders.id AS order_id,
orders.total_price
FROM users
JOIN orders
ON users.id = orders.user_id;- JOIN : テーブルを結合
- ON users.id = orders.user_id : 結合条件
JOINは少し難しめなので、最初は「テーブルを組み合わせるためのもの」くらいの理解でOKです。
自宅で気軽にSQLを触るには?
- SQLite
- インストールも簡単で、ファイル1つで動く軽量DB
- DockerでMySQL/PostgreSQLを立てる
- 本番に近い環境を用意したいときに便利
- ブラウザ上のSQL練習サイト
- SQLZoo / LeetCode / AtCoderなど、SQLの問題を解けるサイトも多数
初心者向けには
- SQLiteやPostgreSQLをローカルに用意
usersのようなテーブルを自分で作る- INSERT / SELECT / UPDATE / DELETE を一通り試す
- そのクエリや学びをブログにメモしていく
といった流れがおすすめです。
まとめ
入門:量子コンピューティングの基本
これからのエンジニアが知っておきたい「量子コンピューティング入門」
ITエンジニアとして開発をしていると、「量子コンピュータ」「量子アルゴリズム」といったキーワードを耳にする機会が増えてきました。
とはいえ、「なんだか難しそう」「数学ガチ勢じゃないと無理そう」という印象を持っている人も多いと思います。
この記事では、プログラマ視点で量子コンピューティングをざっくり理解できるように、
- 量子コンピュータとは何か
- 古典コンピュータと何が違うのか
- エンジニアが今から何をしておくと良いか
を、できるだけ数式ナシで紹介します。
量子コンピュータってそもそも何?
ふだん私たちが使っているPCやスマホは、ビット(0か1)を単位にして計算しています。
一方、量子コンピュータは量子ビット(キュービット)を使います。
キュービットのポイントは、
- 0 と 1 が「どちらか」ではなく、「0 と 1 が重ね合わさった状態」をとれる
- 複数のキュービットが「量子もつれ」と呼ばれる強い相関を持てる
というところです。
プログラマ的にかなり雑に言うと、
「全部のパターンを同時に試しながら、うまく干渉させて正解の確率だけを増幅させる」
ような計算ができる、というイメージです。
どんなところで役に立ちそうなの?
現時点でも、理論的に有望とされている分野はかなりはっきりしてきています。
- 暗号・セキュリティ
- 最適化問題
- 経路最適化、スケジューリング、ポートフォリオ最適化など
- 組み合わせ爆発を起こしやすい問題で、量子的な高速化が期待されている
- 化学シミュレーション・材料設計
- 分子のふるまい自体が量子的なので、量子コンピュータとの相性が良い
- 新素材・新薬の探索コストを大きく下げられる可能性
一方で、「あらゆる計算が量子コンピュータで爆速になる」わけではない点には注意が必要です。
ウェブアプリのCRUD処理や一般的な業務ロジックは、引き続き古典コンピュータの守備範囲です。
現状の量子コンピュータはどのくらい実用的?
よく出てくるキーワードが NISQ (Noisy Intermediate-Scale Quantum) です。
- キュービット数:数十〜数百程度
- エラー率:まだまだ高い
- 完全な量子エラー訂正:未実現
つまり、「まだ研究色が強く、本格的な実用はこれから」という段階です。
ただし、AWSやIBM、Google、Microsoft などがクラウド経由で量子デバイスやシミュレータを公開し始めており、ソフトウェアエンジニアでも触りやすくなっているのがここ数年の大きな変化です。
プログラマ視点で見る量子コンピューティング
量子コンピュータも、ソフトウェアエンジニアにとっては「別のアーキテクチャを持つターゲットマシン」と見ることができます。
古典コンピュータでは、
というレイヤがありますが、量子コンピュータにも、
- キュービット
- 量子ゲート(NOT, Hadamard, CNOT など)
- 量子回路 → 高級量子言語 → コンパイラ
といった構造があります。
実務エンジニアとしては、いきなり量子ゲートを手書きする必要はなく、以下のようなフレームワークを使って「量子回路を組む」ことから入るのが現実的です。
Pythonベースのものが多いので、普段からPythonを書いているエンジニアにとっては学習コストも比較的低めです。
今からエンジニアがやっておくと良さそうなこと
「量子コンピュータを仕事で使う」未来がいつ来るかは読みにくいですが、土台作りとしては、以下を押さえておくと応用が利きます。
- 線形代数の基礎のおさらい
- Python で数値計算・シミュレーションに慣れておく
NumPyやmatplotlibなど- 量子回路シミュレータも多くが Python 前提
- クラウドの量子サービスを軽く触ってみる
- 量子アルゴリズムの「直感的なアイデア」だけでも押さえる
「完全に理解しよう」とするよりも、「だいたい何ができて、どの辺に効きそうか」をつかんでおくことが、現時点ではいちばんコスパが良いと感じています。
まとめ
- 量子コンピュータは、キュービットの重ね合わせや量子もつれを利用して、特定の問題を高速に解ける可能性を持つ計算モデル
- 現状は NISQ 世代で、実験・研究色が強いが、クラウドを通じてソフトウェアエンジニアでも触れる環境が整いつつある
- エンジニアとしては、線形代数・Python・クラウド量子サービスを入り口に、「何ができそうな技術なのか」を把握しておくのがおすすめ
今後は、実際に Qiskit などを使って簡単な量子回路を組んでみるチュートリアルも記事にしていく予定です。
OSI参照モデル
OSI参照モデルとは
はじめに
OSI参照モデル(Open Systems Interconnection Reference Model)は、コンピュータネットワークの通信プロトコルを機能別に7つの階層に分けて定義したモデルです。1984年に国際標準化機構(ISO)によって策定され、ネットワーク通信の理解と実装の標準化を目的としています。
この記事では、OSI参照モデルの各階層について詳しく解説し、実際の通信プロセスでの役割を説明します。
OSI参照モデルの7階層
OSI参照モデルは、下位層から上位層へと以下の7つの階層で構成されています:
┌─────────────────────────────────────┐ │ 7. アプリケーション層 ├─────────────────────────────────────┤ │ 6. プレゼンテーション層 ├─────────────────────────────────────┤ │ 5. セッション層 ├─────────────────────────────────────┤ │ 4. トランスポート層 ├─────────────────────────────────────┤ │ 3. ネットワーク層 ├─────────────────────────────────────┤ │ 2. データリンク層 ├─────────────────────────────────────┤ │ 1. 物理層 └─────────────────────────────────────┘
覚え方
各階層の名前を覚えるための語呂合わせ:
- アプリケーション層
- プレゼンテーション層
- セッション層
- トランスポート層
- ネットワーク層
- データリンク層
- ビ物理層
「アプセトネデビ」と覚えると便利です。
各階層の詳細解説
第1層:物理層(Physical Layer)
役割: 電気信号や光信号などの物理的な伝送媒体を通じて、ビット列(0と1)を送受信する。
主な機能: - ケーブル、コネクタ、信号の電圧レベルなどの物理的な仕様を定義 - ビット列の送受信 - 伝送速度、同期方式の定義
具体例: - イーサネットケーブル(RJ-45コネクタ) - 光ファイバーケーブル - 無線LAN(Wi-Fi)の電波 - USBケーブル
プロトコル例: - 10BASE-T、100BASE-TX(イーサネット) - IEEE 802.11(Wi-Fi)
第2層:データリンク層(Data Link Layer)
役割: 同一ネットワークセグメント内での直接的な通信を管理し、エラー検出・訂正を行う。
主な機能: - フレームの生成と分解 - MACアドレスによる機器の識別 - エラー検出(CRC:巡回冗長検査) - フロー制御
具体例: - スイッチングハブでの通信 - イーサネットフレームの送受信 - MACアドレスによる機器の識別
プロトコル例: - イーサネット(Ethernet) - PPP(Point-to-Point Protocol) - スイッチング(L2スイッチ)
サブレイヤー: - LLC(Logical Link Control): 上位層へのインターフェース提供 - MAC(Media Access Control): 物理層へのアクセス制御
第3層:ネットワーク層(Network Layer)
役割: 異なるネットワーク間での通信を可能にし、最適な経路を選択する(ルーティング)。
主な機能: - IPアドレスによる論理的なアドレッシング - ルーティング(経路選択) - パケットの分割と再構築(フラグメンテーション)
具体例: - インターネット経由での通信 - ルーターによる経路制御 - IPアドレスによる機器の識別
プロトコル例: - IP(Internet Protocol) - ICMP(Internet Control Message Protocol) - ARP(Address Resolution Protocol) - OSPF、BGP(ルーティングプロトコル)
重要な概念: - IPアドレス: ネットワーク上での機器の論理的な住所 - ルーティングテーブル: パケットの転送先を決定するための情報
第4層:トランスポート層(Transport Layer)
役割: エンドツーエンド(送信元から宛先まで)の信頼性の高い通信を提供する。
主な機能: - ポート番号によるアプリケーションの識別 - エラー検出と再送制御 - フロー制御と輻輳制御 - データの分割と再構築
具体例: - WebブラウザとWebサーバー間の通信 - メールクライアントとメールサーバー間の通信
プロトコル例: - TCP(Transmission Control Protocol): 信頼性の高い通信(コネクション型) - 3ウェイハンドシェイクによる接続確立 - エラー検出と再送制御 - 順序保証 - UDP(User Datagram Protocol): 高速だが信頼性が低い通信(コネクションレス型) - リアルタイム通信に適している - エラー検出のみ(再送なし)
ポート番号の例: - 80: HTTP - 443: HTTPS - 25: SMTP - 53: DNS
第5層:セッション層(Session Layer)
役割: アプリケーション間のセッション(通信セッション)の確立、維持、終了を管理する。
主な機能: - セッションの確立と終了 - セッションの同期 - ダイアログ制御(半二重/全二重通信の制御)
具体例: - リモートデスクトップ接続 - データベース接続のセッション管理
プロトコル例: - NetBIOS - RPC(Remote Procedure Call) - SQL
注意: 実際のTCP/IPプロトコルスタックでは、この層の機能はアプリケーション層やトランスポート層に統合されることが多い。
第6層:プレゼンテーション層(Presentation Layer)
役割: データの表現形式(文字コード、圧縮、暗号化など)を変換する。
主な機能: - データ形式の変換(文字コード、画像形式など) - データの圧縮と展開 - データの暗号化と復号化
具体例: - ASCII、UTF-8などの文字コード変換 - JPEG、PNGなどの画像形式変換 - SSL/TLSによる暗号化
プロトコル例: - SSL/TLS(暗号化) - MIME(Multipurpose Internet Mail Extensions) - ASCII、EBCDIC(文字コード)
注意: 実際のTCP/IPプロトコルスタックでは、この層の機能はアプリケーション層に統合されることが多い。
第7層:アプリケーション層(Application Layer)
役割: ユーザーが直接利用するアプリケーションの通信プロトコルを定義する。
主な機能: - アプリケーション固有の通信プロトコルの定義 - ユーザーインターフェースの提供
具体例: - WebブラウザでのWebページ閲覧 - メールの送受信 - ファイル転送
プロトコル例: - HTTP/HTTPS: Webページの取得 - SMTP: メール送信 - POP3/IMAP: メール受信 - FTP: ファイル転送 - DNS: ドメイン名の解決 - SSH: リモートログイン - DHCP: IPアドレスの自動割り当て
データの流れ(カプセル化と非カプセル化)
送信時のカプセル化(Encapsulation)
データが送信される際、上位層から下位層へと進むにつれて、各層でヘッダー(制御情報)が追加されます
アプリケーション層: [データ]
↓
プレゼンテーション層: [プレゼンテーションヘッダー][データ]
↓
セッション層: [セッションヘッダー][プレゼンテーションヘッダー][データ]
↓
トランスポート層: [TCP/UDPヘッダー][セッションヘッダー][...][データ]
↓
ネットワーク層: [IPヘッダー][TCP/UDPヘッダー][...][データ]
↓
データリンク層: [イーサネットヘッダー][IPヘッダー][...][データ][FCS]
↓
物理層: ビット列として送信
受信時の非カプセル化(Decapsulation)
受信側では、下位層から上位層へと進むにつれて、各層のヘッダーが順次取り除かれます
物理層: ビット列を受信
↓
データリンク層: [イーサネットヘッダー]を解析・除去
↓
ネットワーク層: [IPヘッダー]を解析・除去
↓
トランスポート層: [TCP/UDPヘッダー]を解析・除去
↓
セッション層: [セッションヘッダー]を解析・除去
↓
プレゼンテーション層: [プレゼンテーションヘッダー]を解析・除去
↓
アプリケーション層: [データ]をアプリケーションに渡す
OSI参照モデルとTCP/IPモデルの関係
実際のインターネットで使用されているTCP/IPモデルは、OSI参照モデルを簡略化したものです
| OSI参照モデル | TCP/IPモデル | 主なプロトコル |
|---|---|---|
| アプリケーション層 | アプリケーション層 | HTTP, SMTP, FTP, DNS |
| プレゼンテーション層 | (統合) | SSL/TLS |
| セッション層 | (統合) | - |
| トランスポート層 | トランスポート層 | TCP, UDP |
| ネットワーク層 | インターネット層 | IP, ICMP, ARP |
| データリンク層 | ネットワークインターフェース層 | イーサネット, Wi-Fi |
| 物理層 | (統合) | ケーブル, 無線 |
実際の通信例:Webページの閲覧
Webブラウザで https://www.example.com にアクセスする場合の流れ:
- アプリケーション層: ブラウザがHTTPリクエストを生成
- プレゼンテーション層: SSL/TLSで暗号化
- セッション層: セッションを確立
- トランスポート層: TCPでポート443を使用して接続
- ネットワーク層: IPアドレス(DNSで解決済み)にパケットを送信
- データリンク層: MACアドレスでイーサネットフレームを作成
- 物理層: 電気信号としてケーブル経由で送信
受信側では、この逆の順序で処理が行われます。
OSI参照モデルを学ぶ意義
- ネットワークの理解: 通信プロトコルがどのように階層化されているかを理解できる
- トラブルシューティング: 問題が発生した際、どの階層で問題が起きているかを特定できる
- 標準化: 異なるベンダーの機器が相互に通信できるための基準となる
- 教育: ネットワーク技術を体系的に学習するためのフレームワーク
まとめ
OSI参照モデルは、ネットワーク通信を7つの階層に分けて理解するためのモデルです。各階層は特定の役割を持ち、上位層から下位層へとデータがカプセル化され、受信側では逆の順序で非カプセル化されます。
実際のインターネットではTCP/IPモデルが使用されていますが、OSI参照モデルを理解することで、ネットワーク通信の全体像を把握し、トラブルシューティングやシステム設計に役立てることができます。
参考資料
- ISO/IEC 7498-1: Information technology - Open Systems Interconnection - Basic Reference Model
- RFC 1122: Requirements for Internet Hosts
- 各種ネットワーク技術書籍
作成日: 2024年11月 最終更新: 2024年11月
デジタル電流制御
デジタル制御
デジタル制御についての備忘録としてここに記します。
制御プラント
以下の単純な単相ハーフブリッジインバータを制御プラントにして, デジタル制御の議論を行います。

デジタル制御を実現するにはマイクロコントローラを使用します.
Microcontrollers (MCU)
デジタル制御を実現するための組み込みシステムについて
・CPU, RAM, ROM
・A/D, PWM, Timer
を必要とします。
デジタル電流制御
以下の3点に注意します。
・A/Dコンバータを用いた電流検出
サンプリング/変換の時間遅れ
量子化ビットエラー
・CPU内での計算
実行時間の遅延
キャリア信号/基準値の分解能
これらの要件をクリアするMCUが制御に必要になります。
ダブルアップデートでのタイミングチャート
以下にPWMキャリアの山と谷をサンプリングしたダブルアップデートの模式図を示します。

PWMキャリアの山の部分と谷の部分で電流のサンプリングを行い, 各サンプリング間にAD変換と演算を行い, サンプリングして次のサンプリング点にてPWM制御演算を更新することによって制御を実現します。更新タイミングの遅れ時間は, =
=
となります。
また山と谷のサンプリングではなく, 山のみのサンプリングを行った際の遅れ時間は, =
=
となります。
デジタル電流制御
連続時間領域における制御ブロック図を示します。

・ : 伝達関数内の電流フィードバックゲイン
・ : 遅れ時間
・ : ゼロ次ホールド関数
次にデジタル時間領域におけるパルス伝達関数のブロック図を示します。

・ : パルス伝達関数内の電流フィードバックゲイン
・ : サンプリング遅れ時間
パルス伝達関数
・クローズドループパルス伝達関数
・極 z を求めると,
となります。
z 平面での安定性
s平面下では極 は収束, 発散を.
は振動性を表しています。
は負に配置されれば収束し,
が0であれば振動はなくなります。

z平面下では, は収束性を,
は振動性を示します。
が単位円内にあれば収束し,
の角度が0であれば振動はなくなります。
パルス伝達関数
ここで, 極の議論に戻ります。
・安定限界ゲイン
このとき,
となり, 安定限界に極配置されます。
・クリティカルゲイン
のとき,
となり, 臨界制動の挙動をとります。

時間領域における応答
では時間領域における応答を見てみましょう. python control を使用して図示します.
""" time domain response of digital control """ import math import matplotlib.pyplot as plt import numpy as np from control import tf, c2d from control.matlab import step ### 数式 s = tf('s') z = tf('z') L = 1 # インダクタンス ts = 0.2 # サンプリング時間 # ゲイン Kc = L/(4*ts) Kh = L/(2*ts) Ks = L/ts # クローズドループ伝達関数 Wc = (Kc*ts/L)/(z*z - z + Kc*ts/L) Wh = (Kh*ts/L)/(z*z - z + Kh*ts/L) Ws = (Ks*ts/L)/(z*z - z + Ks*ts/L) print(Wc) print(Wh) print(Ws) # 0次ホールドによる離散化 print('discrete time system(zoh)', Wc) print('discrete time system (zoh) ', Wh) print('discrete time system(zoh)', Ws) ### 図示 fig, ax = plt.subplots(1, 3, figsize = (6, 2.6)) #離散時間システム(0次ホールドによる離散化) T = np.arange(0, 4, ts) # Kc = L/4Ts y, t = step(Wc, T) ax[0].plot(t, y, ls = '-', marker = 'o', label = 'Kc = L/4Ts') # Kh = L/2Ts y, t = step(Wh, T) ax[1].plot(t, y, ls = '-', marker = 'o', label = 'Kh = L/2Ts') # Ks = L/Ts y, t = step(Ws, T) ax[2].plot(t, y, ls = '-', marker = 'o', label = 'Ks = L/Ts') title = ['Kc', 'Kh', 'Ks'] for i in range(3): ax[i].set_xlabel('t') ax[i].set_ylabel('y') ax[i].set_title(title[i]) ax[i].legend() fig.tight_layout() plt.show()

のとき, クリティカルゲインとなり振動なく収束します。
のとき, クリティカルゲイン時より早く収束しますが振動成分が残ります。
のとき, 収束はさらに早くなるもののかなり振動の大きい応答になります。
デッドビート制御

・遅延要素
MCU内のサンプリング遅延
電流応答の遅れ(インダクタンスの要素)
少なくとも 2サンプリングは電流応答の遅れがある
デッドビート制御の伝達関数
・2サンプリング遅延のクローズドループ伝達関数であると仮定します
・クローズドループ伝達関数
・ から得られる伝達関数の結果
・極
・実装
・時間領域表現
ブロック図

1サンプリング遅延と加算器で表現されます.
時間応答
では時間応答を見てみましょう。
""" time domain response of digital control """ import math import matplotlib.pyplot as plt import numpy as np from control import tf, c2d from control.matlab import step ### 数式 s = tf('s') z = tf('z') L = 1 # インダクタンス ts = 0.2 # サンプリング時間 # ゲイン Kd = L/ts # デッドビートコントローラ Gz = Kd * z / (z + 1) # オープンループ伝達関数 Goz = Gz * (1/z) * ((ts/L)/(z-1)) # クローズドループ伝達関数 Wz = Goz / (1+Goz) print(Wz) # 0次ホールドによる離散化 print('discrete time system (zoh) ', Wz) ### 図示 fig, ax = plt.subplots(1, 2, figsize = (6, 2.6)) # 連続時間システム Tc = np.arange(0, 4, 0.01) Uc = 1 y, t = step(Uc, Tc) ax[0].plot(t, y, ls = '-') #離散時間システム(0次ホールドによる離散化) T = np.arange(0, 4, ts) y, t = step(Wz, T) ax[0].plot(t, y, ls = '-', marker = 'o', label = 'Dead Beat') title = ['Dead Beat'] for i in range(1): ax[i].set_xlabel('t') ax[i].set_ylabel('y') ax[i].set_title(title[i]) ax[i].legend() fig.tight_layout() plt.show()

2サンプリングで収束することがわかります。
デジタル電流制御②
前回に続いて, 今回は電流制御の応用についての議論を行います.
デッドビート制御

・遅延要素
MCU内のサンプリング遅延
電流応答の遅れ(インダクタンスの要素)
少なくとも 2サンプリングは電流応答の遅れがある
デッドビート制御の伝達関数
・2サンプリング遅延のクローズドループ伝達関数であると仮定します
・クローズドループ伝達関数
・ から得られる伝達関数の結果
・極
・実装
・時間領域表現
ブロック図

1サンプリング遅延と加算器で表現されます.
時間応答
では時間応答を見てみましょう。
""" time domain response of digital control """ import math import matplotlib.pyplot as plt import numpy as np from control import tf, c2d from control.matlab import step ### 数式 s = tf('s') z = tf('z') L = 1 # インダクタンス ts = 0.2 # サンプリング時間 # ゲイン Kd = L/ts # デッドビートコントローラ Gz = Kd * z / (z + 1) # オープンループ伝達関数 Goz = Gz * (1/z) * ((ts/L)/(z-1)) # クローズドループ伝達関数 Wz = Goz / (1+Goz) print(Wz) # 0次ホールドによる離散化 print('discrete time system (zoh) ', Wz) ### 図示 fig, ax = plt.subplots(1, 2, figsize = (6, 2.6)) # 連続時間システム Tc = np.arange(0, 4, 0.01) Uc = 1 y, t = step(Uc, Tc) ax[0].plot(t, y, ls = '-') #離散時間システム(0次ホールドによる離散化) T = np.arange(0, 4, ts) y, t = step(Wz, T) ax[0].plot(t, y, ls = '-', marker = 'o', label = 'Dead Beat') title = ['Dead Beat'] for i in range(1): ax[i].set_xlabel('t') ax[i].set_ylabel('y') ax[i].set_title(title[i]) ax[i].legend() fig.tight_layout() plt.show()

2サンプリングで収束することがわかります。
デジタル電流制御
デジタル制御①
デジタル制御についての備忘録としてここに記します。
制御プラント
以下の単純な単相ハーフブリッジインバータを制御プラントにして, デジタル制御の議論を行います。

デジタル制御を実現するにはマイクロコントローラを使用します.
Microcontrollers (MCU)
デジタル制御を実現するための組み込みシステムについて
・CPU, RAM, ROM
・A/D, PWM, Timer
を必要とします。
デジタル電流制御
以下の3点に注意します。
・A/Dコンバータを用いた電流検出
サンプリング/変換の時間遅れ
量子化ビットエラー
・CPU内での計算
実行時間の遅延
キャリア信号/基準値の分解能
これらの要件をクリアするMCUが制御に必要になります。
ダブルアップデートでのタイミングチャート
以下にPWMキャリアの山と谷をサンプリングしたダブルアップデートの模式図を示します。

PWMキャリアの山の部分と谷の部分で電流のサンプリングを行い, 各サンプリング間にAD変換と演算を行い, サンプリングして次のサンプリング点にてPWM制御演算を更新することによって制御を実現します。更新タイミングの遅れ時間は, =
=
となります。
また山と谷のサンプリングではなく, 山のみのサンプリングを行った際の遅れ時間は, =
=
となります。
デジタル電流制御
連続時間領域における制御ブロック図を示します。

・ : 伝達関数内の電流フィードバックゲイン
・ : 遅れ時間
・ : ゼロ次ホールド関数
次にデジタル時間領域におけるパルス伝達関数のブロック図を示します。

・ : パルス伝達関数内の電流フィードバックゲイン
・ : サンプリング遅れ時間
パルス伝達関数
・クローズドループパルス伝達関数
・極 z を求めると,
となります。
z 平面での安定性
s平面下では極 は収束, 発散を.
は振動性を表しています。
は負に配置されれば収束し,
が0であれば振動はなくなります。

z平面下では, は収束性を,
は振動性を示します。
が単位円内にあれば収束し,
の角度が0であれば振動はなくなります。
パルス伝達関数
ここで, 極の議論に戻ります。
・安定限界ゲイン
このとき,
となり, 安定限界に極配置されます。
・クリティカルゲイン
のとき,
となり, 臨界制動の挙動をとります。

時間領域における応答
では時間領域における応答を見てみましょう. python control を使用して図示します.
""" time domain response of digital control """ import math import matplotlib.pyplot as plt import numpy as np from control import tf, c2d from control.matlab import step ### 数式 s = tf('s') z = tf('z') L = 1 # インダクタンス ts = 0.2 # サンプリング時間 # ゲイン Kc = L/(4*ts) Kh = L/(2*ts) Ks = L/ts # クローズドループ伝達関数 Wc = (Kc*ts/L)/(z*z - z + Kc*ts/L) Wh = (Kh*ts/L)/(z*z - z + Kh*ts/L) Ws = (Ks*ts/L)/(z*z - z + Ks*ts/L) print(Wc) print(Wh) print(Ws) # 0次ホールドによる離散化 print('discrete time system(zoh)', Wc) print('discrete time system (zoh) ', Wh) print('discrete time system(zoh)', Ws) ### 図示 fig, ax = plt.subplots(1, 3, figsize = (6, 2.6)) #離散時間システム(0次ホールドによる離散化) T = np.arange(0, 4, ts) # Kc = L/4Ts y, t = step(Wc, T) ax[0].plot(t, y, ls = '-', marker = 'o', label = 'Kc = L/4Ts') # Kh = L/2Ts y, t = step(Wh, T) ax[1].plot(t, y, ls = '-', marker = 'o', label = 'Kh = L/2Ts') # Ks = L/Ts y, t = step(Ws, T) ax[2].plot(t, y, ls = '-', marker = 'o', label = 'Ks = L/Ts') title = ['Kc', 'Kh', 'Ks'] for i in range(3): ax[i].set_xlabel('t') ax[i].set_ylabel('y') ax[i].set_title(title[i]) ax[i].legend() fig.tight_layout() plt.show()

のとき, クリティカルゲインとなり振動なく収束します。
のとき, クリティカルゲイン時より早く収束しますが振動成分が残ります。
のとき, 収束はさらに早くなるもののかなり振動の大きい応答になります。