Розмір відео: 1280 X 720853 X 480640 X 360
Показувати елементи керування програвачем
Автоматичне відтворення
Автоповтор
以下最終的なプログラムとなっています。動画内で触れるのを忘れてましたがPythonのプログラムも後ろにつけておきます。Pythonに関してはコピペしただけなので解説は難しいかも…const int x7 = A1; // センサー入力const int x6 = 9; // PWM出力float x1, x2, x3, x3_old, x4, x5, x8, x9;float r, t, dt;float Kp, Ki, Kd;unsigned long previousMicros = 0;const unsigned long interval = 3000; // 制御周期3msvoid setup() { Serial.begin(9600); pinMode(x7, INPUT); pinMode(x6, OUTPUT); t = x3_old = x4 = x9 = 0; // 初期化 r = 2.5; // 目標値 Kp = 1.0; // 比例ゲイン Ki = 0.0; // 積分ゲイン Kd = 0.0; // 微分ゲイン dt = 0.003; // 制御周期 // スタート信号を待つ while (Serial.available() == 0) { // 何もせず待機 } // スタート信号を受信 if (Serial.read() == 'S') { Serial.println("Start received"); }}void loop() { unsigned long currentMicros = micros(); // 3ミリ秒ごとに処理を実行 if (currentMicros - previousMicros >= interval) { previousMicros = currentMicros; x1 = r; x2 = x1 - x9; x3 = x2 * 100.0 * (255.0 / 500.0); // x2のままでは小さすぎる x4 = Kp * x3 + Ki * integ(x3,x3_old,x4,dt) + Kd * diff(x3,x3_old,dt); // PI制御 x3_old = x3; x5 = limit(x4, 0, 255); analogWrite(x6, x5); // 制御入力 // x6 → RC回路 → x7 x8 = analogRead(x7); // センサー x9 = x8 * (5.0 / 1023.0); t += dt; Serial.print(t * 1000); // tをミリ秒に変換して出力 Serial.print(","); Serial.print(x8); Serial.print(","); Serial.print(x4); Serial.print(","); Serial.println(x5); }}float limit(float x, float min, float max) { if (x < min) return min; if (x > max) return max; return x;}float integ(float y_in, float y_old, float S_old, float dt) { float S_out = S_old + (y_in + y_old) * dt / 2.0; return S_out;}float diff(float y_in, float y_old, float dt){ float Diff = (y_in - y_old) / dt; return Diff;}----------------------------------------------------------------------------------------------------------------------------------------------#ここから先パイソンimport serialimport pandas as pdimport time# シリアルポートとボーレートの設定 (ポートは環境に合わせて変更してください)ser = serial.Serial('COM1', 9600)# シリアル通信が始まるまで少し待機time.sleep(2) # Arduinoのリセット待ち# Arduinoにスタート信号を送るser.write(b'S') # 'S'を送信# データを格納するリストdata_list = []while True: if ser.in_waiting > 0: # シリアルポートから1行読み取り line = ser.readline().decode('utf-8').rstrip() # 読み取ったデータをコンマ区切りで分割 data = line.split(",") # データが要素を持っているか確認 if len(data) == 4: try: t = float(data[0]) x8 = float(data[1]) x4 = float(data[2]) x5 = float(data[3]) print(f"t: {t}, x8: {x8}, x4: {x4}, x5: {x5}") # データをリストに追加 data_list.append([t, (x8/1023)*5, x4, x5]) # ループを終了する条件 if t >= 300: break except ValueError: print("データの変換に失敗しました:", data)# データの確認print("データリスト:", data_list)# データをDataFrameに変換df = pd.DataFrame(data_list, columns=['t', 'x8', 'x4', 'x5'])# データフレームの確認print("データフレーム:")print(df.head())# Excelファイルに保存 保存したいパスを指定try: df.to_excel(r'F:\フォルダ1\フォルダ2\エクセル.xlsx', index=False, engine='openpyxl') print("データがExcelファイルに保存されました。")except Exception as e: print(f"エラー: {e}")
以下最終的なプログラムとなっています。
動画内で触れるのを忘れてましたがPythonのプログラムも後ろにつけておきます。Pythonに関してはコピペしただけなので解説は難しいかも…
const int x7 = A1; // センサー入力
const int x6 = 9; // PWM出力
float x1, x2, x3, x3_old, x4, x5, x8, x9;
float r, t, dt;
float Kp, Ki, Kd;
unsigned long previousMicros = 0;
const unsigned long interval = 3000; // 制御周期3ms
void setup() {
Serial.begin(9600);
pinMode(x7, INPUT);
pinMode(x6, OUTPUT);
t = x3_old = x4 = x9 = 0; // 初期化
r = 2.5; // 目標値
Kp = 1.0; // 比例ゲイン
Ki = 0.0; // 積分ゲイン
Kd = 0.0; // 微分ゲイン
dt = 0.003; // 制御周期
// スタート信号を待つ
while (Serial.available() == 0) {
// 何もせず待機
}
// スタート信号を受信
if (Serial.read() == 'S') {
Serial.println("Start received");
}
}
void loop() {
unsigned long currentMicros = micros();
// 3ミリ秒ごとに処理を実行
if (currentMicros - previousMicros >= interval) {
previousMicros = currentMicros;
x1 = r;
x2 = x1 - x9;
x3 = x2 * 100.0 * (255.0 / 500.0); // x2のままでは小さすぎる
x4 = Kp * x3 + Ki * integ(x3,x3_old,x4,dt) + Kd * diff(x3,x3_old,dt); // PI制御
x3_old = x3;
x5 = limit(x4, 0, 255);
analogWrite(x6, x5); // 制御入力
// x6 → RC回路 → x7
x8 = analogRead(x7); // センサー
x9 = x8 * (5.0 / 1023.0);
t += dt;
Serial.print(t * 1000); // tをミリ秒に変換して出力
Serial.print(",");
Serial.print(x8);
Serial.print(",");
Serial.print(x4);
Serial.print(",");
Serial.println(x5);
}
}
float limit(float x, float min, float max) {
if (x < min) return min;
if (x > max) return max;
return x;
}
float integ(float y_in, float y_old, float S_old, float dt) {
float S_out = S_old + (y_in + y_old) * dt / 2.0;
return S_out;
}
float diff(float y_in, float y_old, float dt){
float Diff = (y_in - y_old) / dt;
return Diff;
}
----------------------------------------------------------------------------------------------------------------------------------------------
#ここから先パイソン
import serial
import pandas as pd
import time
# シリアルポートとボーレートの設定 (ポートは環境に合わせて変更してください)
ser = serial.Serial('COM1', 9600)
# シリアル通信が始まるまで少し待機
time.sleep(2) # Arduinoのリセット待ち
# Arduinoにスタート信号を送る
ser.write(b'S') # 'S'を送信
# データを格納するリスト
data_list = []
while True:
if ser.in_waiting > 0:
# シリアルポートから1行読み取り
line = ser.readline().decode('utf-8').rstrip()
# 読み取ったデータをコンマ区切りで分割
data = line.split(",")
# データが要素を持っているか確認
if len(data) == 4:
try:
t = float(data[0])
x8 = float(data[1])
x4 = float(data[2])
x5 = float(data[3])
print(f"t: {t}, x8: {x8}, x4: {x4}, x5: {x5}")
# データをリストに追加
data_list.append([t, (x8/1023)*5, x4, x5])
# ループを終了する条件
if t >= 300:
break
except ValueError:
print("データの変換に失敗しました:", data)
# データの確認
print("データリスト:", data_list)
# データをDataFrameに変換
df = pd.DataFrame(data_list, columns=['t', 'x8', 'x4', 'x5'])
# データフレームの確認
print("データフレーム:")
print(df.head())
# Excelファイルに保存 保存したいパスを指定
try:
df.to_excel(r'F:\フォルダ1\フォルダ2\エクセル.xlsx', index=False, engine='openpyxl')
print("データがExcelファイルに保存されました。")
except Exception as e:
print(f"エラー: {e}")