質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

1回答

741閲覧

ペルチェ素子を2つ動作させるプログラムがうまく動かないです

jhfchtrfd

総合スコア1

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

1クリップ

投稿2023/07/31 06:07

編集2023/07/31 07:14

Arduinoの別のポートに繋いだペルチェ素子(シーケンス制御)を1つのプログラムで同時に動作させたいです.このペルチェ素子はPID制御で36度を保ちます.

・リレーを制御するピン それぞれ2と3ポート
・サーミスタのピン   それぞれA0とA1ポート

調査したこと・試したこと

はじめ,ペルチェ素子1つで動作させてみました.それぞれA0とA1のポートにつないだまま個々に動かした場合,うまく36度を保つように動作しました.以下にそのコードを示します.

C

1#include <math.h> 2 3//目標の温度 4double targetTemperature = 36.0; 5 6//リレーを制御するピン 7int enablePin = 3; 8 9 10//サーミスタ関係 11double T; //サーミスタの温度(T) 12int currentTemperture = A1;//サーミスタのピン 13int thermistorPin = A1; 14const float DIVIDER = 10000.0; // 分圧抵抗10kΩ 15const float T0 = 273.15; 16const float R0 = 27700.0; //サーミスタの特性で変わる 17const float B = 3435.0; //サーミスタの特性で変わる 18 19int count = 0; 20double input = 255.0; 21double preinput = 255.0; 22double deltainput = 0; 23double e = 0; 24double e1 = 0; 25double e2 = 0; 26 27double kp = 3.5; //比例ゲイン 28double ki = 1.0; //積分ゲイン 29double kd = 1.4; // 微分ゲイン 30 31void setup() { 32 Serial.begin(9600); 33 pinMode(A1, INPUT); //A0番ピンを入力用に設定する 34 pinMode(enablePin, OUTPUT); 35 pinMode(thermistorPin, INPUT); 36 37 digitalWrite(enablePin, LOW); 38 Serial.println("プログラム開始"); 39} 40 41void loop() { 42 43 currentTemperture = getTemperature(); 44 45 Serial.print(targetTemperature); //目標温度表示 46 Serial.print(", "); 47 Serial.print(currentTemperture); //今の温度表示 48 Serial.println(" at " + String(millis())); 49 50 //Serial.println("Temperature: " + String(currentTemperture) + "C"); 51 52 53 if (targetTemperature <= 24.0) { 54 e = currentTemperture - targetTemperature; 55 } else { 56 e = targetTemperature - currentTemperture; 57 } 58 59 controlRelay(); 60 61 if (count == 0) { 62 e1 = e; 63 preinput = input; 64 } else { 65 e1 = e; 66 e2 = e1; 67 preinput = input; 68 } 69 70 count++; 71 delay(1000); 72} 73 74 75double getTemperature() { //現在の気温を求める 76 float Aout = float(analogRead(thermistorPin)); //アナログピンの電圧を読み取る 77 Serial.println(Aout); 78 float Rt = DIVIDER * Aout / (1024.0 - Aout); //サーミスタの抵抗値を求める 79 80 float result = calcTemp(Rt); 81 return result; 82} 83 84float calcTemp(float Rt) { 85 float T_bar = 1 / T0 + (log(Rt / R0)) / B; //抵抗値から温度1/Tを求める(NTC) 86 return 1.0 / T_bar - 273.15; //温度Tを求める T=t(度)+273.15 87} 88 89void controlRelay() { 90 if (count >= 2) { 91 if (pid() > 255 / 1.3) { 92 digitalWrite(enablePin, HIGH); //電流を流す 93 } else { 94 digitalWrite(enablePin, LOW); //電流を止める 95 } 96 } 97} 98 99 100int pid(void) { 101 deltainput = kp * (e - e1) + ki * e + kd * ((e - e1) - (e1 - e2)); 102 input = preinput + deltainput; 103 input = constrain(input, 0, 255); 104 return input; 105}

問題となるプログラム

次に,2つ動作させるために書き換えたものを以下に示します.この場合,2つのどちらのペルチェ素子の温度も上がっていきませんでした(温度変化がない,HIGHになっていない感じ).いろいろ試行錯誤したため,関数の賢い使い方ができていませんがご了承ください.

C

1#include <math.h> 2 3//目標の温度 4double targetTemperature = 36.0; 5 6//リレーを制御するピン 7int enablePin1 = 2; 8int enablePin2 = 3; 9 10 11//サーミスタ関係 12double T1; //サーミスタの温度(T) 13double T2; 14int currentTemperture1 = A0;//サーミスタのピン 15int thermistorPin1 = A0; 16int currentTemperture2 = A1;//サーミスタのピン 17int thermistorPin2 = A1; 18const float DIVIDER = 10000.0; // 分圧抵抗10kΩ 19const float T0 = 273.15; 20const float R0 = 27700.0; //サーミスタの特性で変わる 21const float B = 3435.0; //サーミスタの特性で変わる 22 23int count1 = 0; 24int count2 = 0; 25double input1 = 255.0; 26double preinput1 = 255.0; 27double deltainput1 = 0; 28double input2 = 255.0; 29double preinput2 = 255.0; 30double deltainput2 = 0; 31double e_1 = 0; 32double e1_1 = 0; 33double e2_1 = 0; 34double e_2 = 0; 35double e1_2 = 0; 36double e2_2 = 0; 37 38double kp = 3.5; //比例ゲイン 39double ki = 1.0; //積分ゲイン 40double kd = 1.4; // 微分ゲイン 41 42void setup() { 43 Serial.begin(9600); 44 pinMode(A0, INPUT); //A0番ピンを入力用に設定する 45 pinMode(enablePin1, OUTPUT); 46 pinMode(thermistorPin1, INPUT); 47 pinMode(A1, INPUT); //A0番ピンを入力用に設定する 48 pinMode(enablePin2, OUTPUT); 49 pinMode(thermistorPin2, INPUT); 50 51 digitalWrite(enablePin1, LOW); 52 digitalWrite(enablePin2, LOW); 53 Serial.println("プログラム開始"); 54} 55 56void loop() { 57 58 currentTemperture1 = getTemperature1(); 59 currentTemperture2 = getTemperature2(); 60 61 Serial.print(targetTemperature); //目標温度表示 62 Serial.print(", "); 63 Serial.print("No.1 "); 64 Serial.print(currentTemperture1); //今の温度表示 65 Serial.print(", "); 66 Serial.print("No.2 "); 67 Serial.println(currentTemperture2); //今の温度表示 68 //Serial.println(" at " + String(millis())); 69 70 //Serial.println("Temperature: " + String(currentTemperture) + "C"); 71 72 73 if (targetTemperature <= 24.0) { 74 e_1 = currentTemperture1 - targetTemperature; 75 e_2 = currentTemperture2 - targetTemperature; 76 } else { 77 e_1 = targetTemperature - currentTemperture1; 78 e_2 = targetTemperature - currentTemperture2; 79 } 80 81 controlRelay1(); 82 controlRelay2(); 83 84 if (count1 == 0) { 85 e1_1 = e_1; 86 preinput1 = input1; 87 } else { 88 e1_1 = e_1; 89 e2_1 = e1_1; 90 preinput1 = input1; 91 } 92 93 if (count2 == 0) { 94 e1_2 = e_2; 95 preinput2 = input2; 96 } else { 97 e1_2 = e_2; 98 e2_2 = e1_2; 99 preinput2 = input2; 100 } 101 102 count1++; 103 count2++; 104 delay(1000); 105} 106 107 108double getTemperature1() { //現在の気温を求める 109 float Aout1 = float(analogRead(thermistorPin1)); //アナログピンの電圧を読み取る 110 //Serial.println(Aout); 111 float Rt1 = DIVIDER * Aout1 / (1024.0 - Aout1); //サーミスタの抵抗値を求める 112 113 float result1 = calcTemp1(Rt1); 114 return result1; 115} 116 117double getTemperature2() { //現在の気温を求める 118 float Aout2 = float(analogRead(thermistorPin2)); //アナログピンの電圧を読み取る 119 //Serial.println(Aout); 120 float Rt2 = DIVIDER * Aout2 / (1024.0 - Aout2); //サーミスタの抵抗値を求める 121 122 float result2 = calcTemp2(Rt2); 123 return result2; 124} 125 126float calcTemp1(float Rt1) { 127 float T_bar1 = 1 / T0 + (log(Rt1 / R0)) / B; //抵抗値から温度1/Tを求める(NTC) 128 return 1.0 / T_bar1 - 273.15; //温度Tを求める T=t(度)+273.15 129} 130 131float calcTemp2(float Rt2) { 132 float T_bar2 = 1 / T0 + (log(Rt2 / R0)) / B; //抵抗値から温度1/Tを求める(NTC) 133 return 1.0 / T_bar2 - 273.15; //温度Tを求める T=t(度)+273.15 134} 135 136void controlRelay1() { 137 if (count1 >= 2) { 138 if (pid1() > 255 / 1.3) { 139 digitalWrite(enablePin1, HIGH); //電流を流す 140 } else { 141 digitalWrite(enablePin1, LOW); //電流を止める 142 } 143 } 144} 145 146void controlRelay2() { 147 if (count2 >= 2) { 148 if (pid2() > 255 / 1.3) { 149 digitalWrite(enablePin2, HIGH); //電流を流す 150 } else { 151 digitalWrite(enablePin2, LOW); //電流を止める 152 } 153 } 154} 155 156 157int pid1() { 158 deltainput1 = kp * (e_1 - e1_1) + ki * e_1 + kd * ((e_1 - e1_1) - (e1_1 - e2_1)); 159 input1 = preinput1 + deltainput1; 160 input1 = constrain(input1, 0, 255); 161 return input1; 162} 163 164int pid2() { 165 deltainput2 = kp * (e_2 - e1_2) + ki * e_2 + kd * ((e_2 - e1_2) - (e1_2 - e2_2)); 166 input2 = preinput2 + deltainput2; 167 input2 = constrain(input2, 0, 255); 168 return input2; 169} 170

どなたかご教授ください.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tmp

2023/07/31 10:44

サーミスターの計算等、わかりませんが、わざわざ2つの過去の値のeを保存していることから eの1つ前の値が、e1で、その前がe2ですか? だとすると、 e1 = e; e2 = e1; ではなく、 e2 = e1; e1 = e; 順になるとおもいますが、e2の値がどれだけ影響するか、わかりませんが問題ないですか?
jhfchtrfd

2023/07/31 13:05

お返事が遅くなってしまって申し訳ありません. 1つ目のプログラム(ペルチェ素子1つのとき)ではちゃんとPID制御ができていたので,それについては問題ないと思います.
tmp

2023/07/31 14:39

サーミスターの最初の温度などの状態が、1つの時と2つの時は、同じでないから結果で異なる結果になったとおもい、 PIDの計算でON/OFFの基準を決めているので影響がでてるのではないかと考えたわけです。
setoppu

2023/07/31 18:46

1つのときにちゃんと動いていた‥というのが謎ですが、 プロトタイプ宣言無くて大丈夫なんです?
thkana

2023/08/01 03:50

この機会にC++の「クラス」について調べてみるのもいいと思います。
jhfchtrfd

2023/08/01 04:04

すみません.昨日の状態からなにも変えていないのですが,今日もう一度やり直したらうまく動きました.接触の問題とかなのでしょうか. ご迷惑をおかけしました.
thkana

2023/08/01 08:58

setoppuさん プロトタイプは、Arduino IDEがよろしくやってくれるみたいです。 そもそもArduinoでは、コンパイル時にsetup()やloop()を組み込んだmain()を内部的に生成するので、その際にユーザーが定義した関数の配置を変えたりしているようです。
guest

回答1

0

自己解決

翌日もう一度動かしたら,うまく動作しました.

投稿2023/08/02 03:08

jhfchtrfd

総合スコア1

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問