ラベル Arduino の投稿を表示しています。 すべての投稿を表示
ラベル Arduino の投稿を表示しています。 すべての投稿を表示

2014年10月28日火曜日

Google Maps API V3でトレースしていくローバー

前回のブログでGoogle MapsのAPIキーの取得ができたました。
それから、家に帰ってから一日一時間くらいコード書きに費やして、週末地区の旅行に行ったり、いろいろあったが、何とかでけた。


最終目的はGooglemapで現在位置から四角いエリアを指定して、エリア内を隈なくトレース線を引き、その線に沿って実際の場所をトレースしていくローバーを作ろうかと。

エリア指定と自動トレース線生成機能はHTML5のJavaScriptでできました。




HTML5なので、容易にスマフォアプリにできます。

プログラミングは、基本的に ここのサンプルコード をコピペするだけの簡単なお仕事なんですが、ごたぶんにもれず、何箇所かはまったので。備忘録として。

まず、APIキーで実行できるサイトのドメインは公開 API へのアクセスで、リファラーで指定。
そのせいと思われるが、ローカルファイルで実行すると、JavaScriptアラートがでて実行できない。
いろいろしらべてみたが、結局、会社のサイトにFTP転送してデバックした。
それほど手間でないからいいけど。

現在位置の取得は Geolocationサンプル の丸写しでいいのですが、最初、会社のブラウザでは長野県庁、家のブラウザでは伊那市市役所が現在位置になりました。たぶんプロバイダのDNSの住所なんでしょうね(会社はOCN.家は伊那ケーブルテレビなんで)
で、ローバー実験場所が公園を想定していたので、会社の近くの春日公園の緯度、経度を指定。
で、ここでめんどくさいので 位置の変数posはグローバル変数にした。
 // Try HTML5 geolocation //春日公園 35.837382, 137.948009
var pos = new google.maps.LatLng(35.837382, 137.948009);
if(navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
とりあえず、現在位置を取得するコードはコメントアウトして、その下にずらずらとコードを書いた。
ある程度上手くいったので現在位置を取得するようにコメントアウトを外すと、上手くいかない。
現在位置取得までタイムラグがあるんかな?。
いろいろ調べてみると、成功コールバック関数使って、現在位置を取得出来たらnavigator.geolocation.getCurrentPosition(function(position) {} ブロックを呼び出すとのこと。
こいつは非同期関数とのことでなので、コードの上からの順でやっているわけではない。
まぁ、現在位置は刻々と変わることが多いので、非同期が都合がよいわな。
確かに現在位置が取得できた時点でpos 変数は上書きされている。
が、そのタイミングは不定なので、下に書いたコードが先に実行されてしまう
現在位置が取得された時点で成功コールバック関数のブロックが有効になるということなので、Pos 変数を使ういろいろな処理は成功コールバック関数ブロック内に書くか、ブロック内から処理関数を呼び出せばいいようだ。
非同期のコールバック関数とか慣れてないので、はまった。

次に現在位置から北に50m、そこから東に50m、そこから南に50m、そして出発点の戻るエリアを書きたい。
GoogleMap上では緯度、経度で位置指定するので、距離とか方向で場所を指定するには計算しなければならない。
難しくはヒュベニの式を用いた、緯度・経度と距離・方位の相互変換の解説ということだが、ちゃんとジオメトリ ライブラリで計算するcomputeOffset() 関数は用意されているので簡単である。

var spherical = google.maps.geometry.spherical;
north = spherical.computeOffset(pos, 50, 0);

とすれば北50mの座標が取得できる。

編集するポリゴンのサンプルがあったので、ほぼ丸写し。
ただポリゴンの各辺中間のゴーストポイント(GP)という動かせるポイントがあって、GPを動かすとさらにGPが出来るといった具合にどんどん複雑なエリアに編集できる。
これはちょっと都合が悪いのでGPを無効にしたい。
調べると、API-V2では頂点数の指定ができたらしいが、V3からは無いので、このままのようです。

動かしたポリゴンの頂点の座標はポリゴンのオブジェクトをdrivePolyとして
var polyPath = drivePoly.getPath();
で配列に代入して north = polyPath.getAt(1);
で配列から取り出します。
http://stackoverflow.com/questions/14948337/getpaths-polygons-google-maps-api
らへんを参考にしました。

あとは、ポリゴンの頂点座標から対角線1mずつ内側に線を引いていくようにして、ローバーのトレース線を引くようにしました。

いちお、ほかに参考になる資料としてサイトを検索しましたが、API V2版の解説が多いですね。
API-V2からV3の変更点が載っていた書籍がgoogleブックスで発見。

Google API Expertが解説する Google Maps APIプログラミングガイド

著者: 勝又 雅史、古籏 一浩、石丸 健太郎、安藤 幸央ちゃんとこれ読めばいいのですが、ちょっとしか見てないです。
あと、グーグルグループのGoogle-Maps-API-Japanなんかには最新情報があります。

ローバーはタミヤのラジコンカーを改造予定。仕事の合間に今年中の完成目標です。
できるかな?
駆動はステッピングモーターかな?ブラシレスモーターのESCにつなぐのもラジコンの応用が出来ていいんだけど。

ヨドバシカメラで7千くらい、すぐ買って試したいがプログラムができるまで我慢。

2014年10月17日金曜日

Arduinoを用いたテンパー炉、リフロー炉の温度制御装置 (設定温度スイッチ)

前回のテンパー炉自作のブログで、
LCDキャラクタディスプレイモジュール(16×2行バックライト付)
いわゆるSC1602シリーズのキャラクター液晶が無事表示できましたので
テンパー炉の温度設定するためにスイッチを2個付けました。
左のスイッチは100の桁を、右のスイッチは10の桁をインクリメントする。



スイッチの入力はArduinoリファレンスで digitalRead() を見てこれかなと思ったが、
【書籍】作って遊べるArduino互換機で、スイッチでの割り込み処理の方法がありました。
attachInterrupt(interrupt, function, mode) を使うのですが、これもピン使用に癖があった。
お約束であまったピンにつけたが動かない。
まぁ、attachInterruptでピン指定がないのでわかりそうなもんですが、よく読むと

「Arduinoボードは割り込み0(ピン2)と割り込み1(ピン3)の外部割り込みに対応しています」

ということでデジタル2,3ピンにスイッチをつなぐようです。
でつないだところちゃんと動きました。

が、チャタリングのせいでスイッチを押すと設定値が2-3飛んでしまいます。
チャタリングはCRで除去する回路を組むのが一般的です。
が、配線も面倒なので
attachInterruptで指定する処理関数でディレイすればいいかな?
とおもいましたが、ディレイ中でも何度も処理関数を呼んでくれるようです。
ちゃんとした割り込み処理ですね。

なので、一回目にスイッチを押した時間を記憶して、次は0.2秒以上たってないと処理しないようにしました。



void L_Pushed() {
  if ((millis() - inter_time) > 200 ) {
    Setpoint += 100;
    if (Setpoint > 400) {
      Setpoint -= 400;
    }
    inter_time = millis();
  }
}

こんな感じです。


ということで、なんとなく、いまさらながらArduinoのつなぎ方がわかりました。
今のところわかってる指定されたピンは

MAX31855使用 K型熱電対アンプモジュール使われたSPI通信では
デジタルピン10(変更可)、11,12,13を使います。
 (ATmega168/328を搭載するボード): 10(SS)、11(MOSI)、12(MISO)、13(SCK)

 また、analogWrite(pin, value)でPWMが使えるピンは
ATmega168/328を搭載しているボードでは、デジタルピン3, 5, 6, 9, 10, 11

デジタル0,1ピンはシリアル通信。

I2CのWireライブラリより
SDA(データライン)はアナログ入力ピン4、SCL(クロックライン)はアナログ入力ピン5です。 
→今回はI2C使いません。

とうことでデジタルピンがほとんど埋まってしまったので、前回のブログに書いたように
LCDキャラクタディスプレイモジュール(16×2行バックライト付)
いわゆるSC1602シリーズのキャラクター液晶はアナログピンにつなぐ事になりました。


マイコン基板、液晶、SSR放熱板を板の上にネジ止め

ソリッド・ステート・リレー(SSR)キット 25A(20A)タイプですが、
PC電源の壊れたやつから取った適当なヒートシンクにつけていましたが、結構熱くなってる。
推奨は40度以下に冷やせとのこと。
次に初代ペンティアムCPUで使っていたヒートシンクにネジ穴あけてつけてみましたが、まだあつい。

最終的に、Intel Pentium Ⅲ、Slot1のヒートシンクにつけてみました。





320度の制御をしてみましたが、以下のように少々ハンチングが起きています。

PIDのオートチューニングのライブラリはまだ入れていません。



ついでに、現在温度をシリアル通信でPCに取り込むのがいいだろう。
で、あまっているBluetoothモジュールをSPPでつけました。

回路は HC-06 Bluetooth to serial adapter を参照しました。

以前、中国通販で500円くらいで買ったものです。
5V電源でないと安定しないようです。
また、スケッチの書き込みには対応出来ませんでした。

いちおArduino-PC間 bluetooth接続を参照し、スケッチ書き込みは難しいとのこと。

まぁこれは仕方なし。

今後は温度プロファイルのPCからの書き込みにも使おうかとおもっています。

ちなみに
Bluetoothシールド_SeeedStudio
なるものも買ってしまいましたが、こちらもスケッチ書き込みは出来ないみたい。
BTモジュールはDTR信号ないですからね。

技適に対応している秋月電子¥1,500
マイクロチップ Bluetoothモジュール RN-42-I/RM
も試してみたいです。
いっぱい買えば安くなるかな。

いまのところのスケッチはこんな感じです。



// K型熱電対温度センサモジュールキット(SPI接続)MAX31855使用(5V版/3.3V版)サンプルスケッチ参照
// Switch-Science 2013.5.14(Tue)
#include "Arduino.h"
#include <SPI.h>
#include <Wire.h>
#include <PID_v1.h>
#include <LiquidCrystal.h>

#define SLAVE 10
#define RelayPin 5
//LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(14, 15, 16, 17, 18, 19);
//PID
double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint, 2, 5, 1, DIRECT);
int WindowSize = 5000;
unsigned long windowStartTime, inter_time;

void setup() {
  //7ピン 5V設定
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);
  //6ピン GND 設定
  pinMode(6, OUTPUT);
  digitalWrite(6, LOW);
  //4ピン GND 設定
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);

  //2ピン input pullup
  pinMode(2, INPUT_PULLUP);
  //3ピン input pullup
  pinMode(3, INPUT_PULLUP);
  //タクトスイッチ 割り込み処理
  //L push 3ピン
  attachInterrupt(1, L_Pushed, FALLING);
  //R push 2ピン 
  attachInterrupt(0, R_Pushed, FALLING);

  Serial.begin(9600);
  //SPIのSS
  pinMode(SLAVE, OUTPUT);
  digitalWrite(SLAVE, HIGH);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  SPI.setDataMode(SPI_MODE0);

  //ヒーターへPWM出力
  pinMode(RelayPin, OUTPUT);     
  digitalWrite(RelayPin, LOW);
  Setpoint = 200;
  //turn the PID on
  myPID.SetMode(AUTOMATIC);

  lcd.begin(16, 2);
  lcd.clear();

}

void loop() {
  unsigned int thermocouple; // 14-Bit Thermocouple Temperature Data + 2-Bit
  unsigned int internal; // 12-Bit Internal Temperature Data + 4-Bit
  double disp; // display value
  char buf[16];
  delay(1000);

  digitalWrite(SLAVE, LOW);                             //  Enable the chip
  thermocouple = (unsigned int)SPI.transfer(0x00) << 8;   //  Read high byte thermocouple
  thermocouple |= (unsigned int)SPI.transfer(0x00);       //  Read low byte thermocouple
  internal = (unsigned int)SPI.transfer(0x00) << 8;       //  Read high byte internal
  internal |= (unsigned int)SPI.transfer(0x00);           //  Read low byte internal
  digitalWrite(SLAVE, HIGH);                            //  Disable the chip

  if((thermocouple & 0x0001) != 0) {

    lcd.setCursor(0,0);
    if ((internal & 0x0004) !=0) {
      lcd.print("Short to Vcc");
    }
    if ((internal & 0x0002) !=0) {
      lcd.print("Short to GND");
    }
    if ((internal & 0x0001) !=0) {
      lcd.print("Open Circuit");
    } 
  }
  else {
    if((thermocouple & 0x8000) == 0){ // 0℃以上   above 0 Degrees Celsius
      disp = (thermocouple >> 2) * 0.25;
    }
    else {   // 0℃未満   below zero
      disp = (0x3fff - (thermocouple >> 2) + 1)  * -0.25;
    }

    Serial.print(disp);
    Serial.println();
    //K温度をLCDに表示
    dtostrf(disp, 3, 0, buf);
    lcd.setCursor(0,0);
    lcd.print("P:");
    lcd.print(buf);
    lcd.print((char)0xdf);
    lcd.print('C');
    //設定温度をLCDに表示
    dtostrf(Setpoint, 3, 0, buf);
    lcd.print(" S:");
    lcd.print(buf);
    lcd.print((char)0xdf);
    lcd.print('C');
    //温度センサーの出力をPIDライブラリに渡す
    Input = disp;
    myPID.Compute();            //計算の実行
    analogWrite(RelayPin, Output);      //analogWriteはPWM出力。計算された数値はOutputに入っている

  }

  if((internal & 0x8000) == 0){ // 0℃以上   above 0 Degrees Celsius
    disp = (internal >> 4) * 0.0625;
  }
  else {                          // 0℃未満   below zero
    disp = (((0xffff - internal) >> 4) + 1)  * -0.0625;
  }

  // 室温温度をLCDに表示
  dtostrf(disp, 3, 0, buf);
  lcd.setCursor(0,1);
  lcd.print("R:");
  lcd.print(buf);
  lcd.print((char)0xdf);
  lcd.print('c');

}

void L_Pushed() {
  if ((millis() - inter_time) > 200 ) {
    Setpoint += 100;
    if (Setpoint > 400) {
      Setpoint -= 400;
    }
    inter_time = millis();
  }
}

void R_Pushed() {
  if ((millis() - inter_time) > 200 ) {
    Setpoint += 10;
    if ((int)Setpoint % 100 == 0) {
      Setpoint -= 100;
    }
    inter_time = millis();
  }
}

2014年10月15日水曜日

Arduinoを用いたテンパー炉、リフロー炉の温度制御装置(I2C液晶壊れる。)

Arduinoを用いたテンパー炉、リフロー炉の温度制御装置で、
白金抵抗素子の温度表示の液晶は
I2C接続小型キャラクタLCDモジュール 8x2行 AQM0802A
320円と安いし、使用していた。
I2Cで2ピンで制御できるのは便利だけど。3.3V電源も必要。

しかし、こやつはリードの足が1.5㎜ピッチと使いにくい。
なので無理やり2.54㎜ピッチのユニバーサル基板に足を広げて使っていた。
が、白金抵抗素子に取り付けていたI2C接続小型キャラクタLCD使わなくなった。
ので、液晶もそのままにしときゃーいいのに取り外そうとしたら壊れてもうた。
ちょっと力いれたら割れたorz... 
で、もう一台買ってあったので1.5㎜ピッチに近い1.27㎜ピッチの表面実装変換パッドに実装。


ピンの付け根の少し上にうっすら白い線が…
最初上手く映っていたが、抵抗の位置かえたりと、いじってたら、そのうち表示しなくなった。
どうも,ピンに付け根にストレスかかって、いかれてもうた。
素直にI2C接続小型LCDモジュールピッチ変換キットとか買っとけばよかったけど。
600円だからね。

で、いつ買ったか記憶がないくらい前に買ってあった。
LCDキャラクタディスプレイモジュール(16×2行バックライト付)
いわゆるSC1602シリーズのキャラクター液晶。


表示画面もデカいし、バックライトなければ500円と安い。
しかし、シリアル通信でなく、4ビットパラレルバスで接続する。
rwを常時WriteにGND接続しても rs, enable, d4, d5, d6, d7と接続に6ピンいる。 
キャラクターLCD表示ライブラリ と LiquidCrystal() なんかを参照して接続。
当初デジタルピンを使っていたが、スイッチとか使ったら(後述)液晶につなぐのに足りなくなってしまった。
でアナログピンに液晶が使えるかを以下を調べてみたが、使えるかいまいちわからない。

Arduinoチュートリアル 基礎編 アナログ入力ピンより
Arduinoのアナログ入力ピンA0-A5には、
14から19までのピン番号が割り振られ、デジタルピンとして使える。
Arduinoボードの違いまとめ(Uno, MEGA 2560, Leonardo, Due)よりUnoの場合を確認。

わからないのでやってみようとアナログ入力ピンA0-A5の6本に液晶を接続。


#include <LiquidCrystal.h>
//LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(14, 15, 16, 17, 18, 19);


とアナログピンを指定したらすんなり表示した。やったね。
で、無事デジタルピンはあいてくれた。


2014年10月9日木曜日

秋月電子 ATMEGA168/328用マイコンボード にブートローダー書き込み

前回 【書籍】作って遊べるArduino互換機を作成したものの、FT232RLの表面実装はんだ付けがいまいちだった。
安定したArduino互換機を作りたい。
秋月電子 ATMEGA168/328用マイコンボード(I/Oボード)
の、基板を前回かってあるので、これを使かおうかと。

この基板のUSBシリアル変換の部分は以下のモジュールを利用。
FT232RL USBシリアル変換モジュール
完成品なので表面実装の半田付けは不要!
モジュールは他のマイコン用に2年ほど前に2つかってあるのでこれを使います。

やり方は秋月電子 Arduino互換ボードの使い方を参照した。

ATMEGA168/328用マイコンボード回路図を見るといらなそうな部品が多い。
まず電源周りだが、DC5VのACアダプタを使っている。
ので、ブリッジダイオードは基板両面で抵抗の切った足のジャンパーでクロス配線。
レギュレーターもいらないのでVin-Voutをジャンパーで飛ばす。
電源セレクタースイッチをつけないので、電源入力とEXTをジャンパーで飛ばす。
(気が付かず、ちょっとはまった)
最初このジャンパーに気が付かず、ICに電源が来てなくてちょっとはまった。
いちおう電解コンデンサを。手持ちで一番背の低いのが330μFの16Vをつけた。

部品を減らしたらスカスカな基板
リセットスイッチは、ほとんど使えわないのでつけなかった。
基板のX4端子、シリアルのジャンパーもしておく。
ワイヤが刺さるように変換モジュールをユニバーサル基板につけ、丸ピンソケットをわきに配置した。ついでにCB0,CB1にLEDをつけて通信状態をモニタできるようにした。

で、ブートローダーの書き込みは基板にあるICSP端子を利用して書き込みした。
  • CTS -> ICSP端子(1:MISO)
  • DSR -> ICSP端子(3:SCK)
  • DCD -> ICSP端子(4:MOSI)
  • RI ->   ICSP端子(5:RESET)
  • GND-> ICSP端子(6:GND)

というわけで、1000円以下の格安で作成できました。

2014年10月7日火曜日

【書籍】作って遊べるArduino互換機を買ってみたものの。

【書籍】作って遊べるArduino互換機を買った。
arduino互換機を作成する為、AVRマイコンにブートローダーを書き込みたかったからだ。
将来的には3.3Vで動くarduino互換機を作成したいし。

書籍には付属基板があり、秋月の部品セット1000円、AVRマイコンを前回購入してある。
『作って遊べるArduino互換機』パーツセット

基板の組み立てはUSB-シリアルコンバータのFT232RLが表面実装ですごく細かい。
amazonのレビューでは「あまりに細かく素人には無理」とのこと。
まぁ、出来るだろうとおもったがはまった。
まず、チップを両面テープで固定してからクリーム半田を盛って加熱。
所々ブリッジしていたので、はんだ吸い取り線で半田を吸い取りなじませた。
半田が取れすぎてしまったようなところは、再度ハンダをもった。
その際、又ブリッジが起きてしまうが、ホームセンターで売ってる半田フラックスを、つま楊枝で足に塗ってから半田コテをあてて直した。
下手にはんだ吸い取り使うより、最初から細い半田コテではんだ付けして、ブリッジしたところだけ直すいつもの方法にしておけばよかった。

半田吸い取り線を強く当てたせいか、基板のパッドが曲がってしまった。
きれいに出来たが、一箇所、基板のパッドが少し曲がってしまった。
半田こての先で加熱しながら矯正。

とりあえず、テスターでは隣の足とのショートしておらず、オープンもしていないのでOK.
その他の部品を付いた。
USBに基板をつなげるとFT232RLのドライバーを認識したので、USB側は、はんだ不良は起きていない様子です。

さっそく書籍にあるようにヒューズの読み込みをはじめましたがエラー。
エラー内容よりUSB変換チップから先のAVRの書き込みが上手くいっていないみたい。

でFT232RLのピン足に半田を当てて再ハンダしてみるがうまくいかない。
(結局、このAVRとの通信エラーの原因は、ICソケット2階建てにしていたため。
(2階建てにして、ブートローダーを書き込んでから、ほかですぐ使えると目論んだ。))

で、いろいろいじっていると、PCでFT232RLを認識しなくなってしまった。
テスターで調べるとUSBの電源マイナスとデータ線がショートしている。
調べるとFT232RLチップの下の部分でショートしている模様。
半田でいじってもどうにも直せず、結局チップの片側の足を全はずしorz...。


ピンセットを差し込みながら加熱してチップのかた側を浮かせた。
パターンに接続されてない基板のパッドはみな取れてしまった。
で、なんとか直して、ヒューズもブートローダーの書き込みはできたけど、不安要素ありすぎ。

なので
秋月電子 ATMEGA168/328用マイコンボード(I/Oボード)
の、基板だけを前回かってあるので、これを使かおうかと。
この基板のUSBシリアル変換の部分は以下のモジュールを利用。
FT232RL USBシリアル変換モジュール
なので表面実装の半田付けは不要!
モジュールは他のマイコン用に2年ほど前に2つかってあるのでこれを使います。

やり方は以下を参照して。
秋月電子 Arduino互換ボードの使い方

備考。
ブートローダーの書き込みはオープンソースで開発されていて、 Atmel AVRシリーズのプログラマ(ライタ)や開発機器をコントロールするプログラム、avrdudeつかいます。

しかし、avrdude ではFT245R/FT232R をサポートされていない模様ですが、
以下のサイトからavrdude のFT245R/FT232R対応版 を書き込みソフトを入手します。
すzのAVR研究 FT245R/FT232R で avrdude (2)avrdude-serjtag04e.zip 

又以下のツールを使うとGUIで書き込みできる
avrdude-GUI (yuki-lab.jp Version)
後書き込みに必要なライブラリ
libusb-win32
を入手。
使用法は書籍にあったとおりでやりました。
以下のサイトを始めいろいろ説明があります。
avrdude-serjtag が serjtag-0.3.zipでちょっと情報が古いですが。

ヒューズ読み込みの際のエラー内容は以下。

avrdude.exe: BitBang OK 
avrdude.exe: pin assign miso 3 sck 5 mosi 6 reset 7
avrdude.exe: led pin assign rdy 10 pgm -1 
ft245r_drain called but queue is not empty 1 
avrdude.exe: drain OK 

ft245r:  bitclk 76800 -> ft baud 38400
ft245r: set CBUS 40 -> 0
ft245r: set CBUS 40 -> 0
ft245r: set CBUS 40 -> 0
ft245r: set CBUS 40 -> 0
ft245r: set CBUS 40 -> 0
ft245r: set CBUS 40 -> 0
avrdude.exe: ft245r_program_enable: failed
avrdude.exe: initialization failed, rc=-1
             Double check connections and try again, or use -F to override
             this check.
ft245r: set CBUS 40 -> 0
avrdude.exe done.  Thank you.


ところで、3.3V仕様のarduino互換機を作ろうと思ったが、
使用しようと思った手持ちにあるbluetoothモジュールが5V 電源だった。
I2C接続小型キャラクタLCDモジュール 8x2行 AQM0802Aは3.3Vだが、

MAX31855使用 K型熱電対アンプモジュールは3.3vレギュレータ付属していた。
で、5V電源のマイコンで作れそうです。

2014年10月3日金曜日

Arduinoを用いたテンパー炉、リフロー炉の温度制御装置(3) (PID制御)

前回K型熱電対アンプモジュールでの温度測定がうまくいきました。
ので、早速オーブントースターのヒーターを秋月のソリッド・ステート・リレー(SSR)キット 25A(20A)タイプでPID制御してみます。
秋月のSSRキットをはんだ付けして組み立ててから、適当なヒートシンクにつけます。
サーモスタットの片方を半田ごてで取り外してSSRの出力にはんだ付け、もう片方に銅線をはんだ付けして、サーモスタットの線を取ったところにはんだ付けします。
サーモスタットは必要ないのですが、どこか適当な温度になるところにつけて安全装置にする予定です。

SSRの入力は以下のサンプルスケッチにあるように6ピンにしました。
これも前回と同じく、やりやすいように0ピンにしましたがうまくいかず。
実はデジタル0,1ピンはシリアル通信用に使用してるとのことで、使えないことが判明。
素人ですね。

PID制御とは
P:Proportinal 比例、I:Integral 積分、D:Derivative 微分
の頭文字。
「フィードバック制御の一種であり、入力値の制御を出力値と目標値との偏差、その積分、および微分の3つの要素によって行う方法のことである」(wikipedia)
ということなんですが、前の会社にいるとき、理化工業の温調器で薬品槽の温度管理をしており、それがPID制御でしたので名前と簡単な原理は知っています。しかしどうゆう数式でやってるかとかは知らない。
最近は倒立振子やクアッドコプターのモータのPID制御が流行ってるっぽい。

PIDのスケッチは、まず、ArduinoのPID Libraryダウンロード
解凍したフォルダ内の \PID_v1 フォルダをArduinoのインストールフォルダー内のlibraries\以下のにフォルダごとコピー。
スケッチはPID RelayOutput ExampleのBasicをもとに、設定温度200度にしてやってみます。

測定温度を一秒置きにシリアル出力させた。
コンソールで受信したデータをエクセルにコピペしてグラフにしたのが以下


2分くらいで240度位までオーバーシュートしました。
が、3分くらいから200度で安定しました。
スケッチ内のPIDに設定値をいろいろいじるとあまりオーバーシュートせずうまくいくようです。
が、とりあえずわからないのでデフォ。
ライブラリのサンプルではPID Adaptive Tuning とか、 there is also now a PID Autotune Library that can help you determine tuning parameters.とかある、説明を見たがが、どうやるかわからん。AutoTune_Example.pdeがあったので何とかオートチューニングできそうだ。

ヒーターオンオフがSSRなので、PWM制御でもってヒーターの中途半端な加熱が可能です。
しかしハンダごて温度コントローラの製作より、
「秋月のSSRキットは、制御部にゼロクロスタイプのフォトトライアックを使っているので、出力波形は必ずゼロクロスのタイミングでON/OFFされ、従ってスイッチングノイズの発生がありません。
」ということ、60hzの分解能のPWMになるのだろうか。


PIDライブラリのサンプル RelayOutputにはリレー用のON,OFF制御のスケッチがありました。
やってみましたが、温度が上昇しすぎてうまくいきません。

PID設定値の加減でしょうが、わからないので、とりあえずPWMでやろうと思います。
 
次回はオーブントースターを組み立ててとりあえず納品しようと思います。ファンなんかはまたあとで。

今回ちょっとはまった、というか、間違え。
PID LibraryOlder Versions からダウンしてしまった。
以下のエラーがでてコンパイルできない。

libraries/PID_v1/PID_v1.cpp: In constructor 'PID::PID(double*, double*, double*, double, double, double, int)':
libraries/PID_v1/PID_v1.cpp:26: error: 'millis' was not declared in this scope
libraries/PID_v1/PID_v1.cpp: In member function 'void PID::Compute()':
libraries/PID_v1/PID_v1.cpp:43: error: 'millis' was not declared in this scope
調べてみると
http://forum.arduino.cc/index.php?topic=158261.0 より Latest version (now hosted on GitHub)からダウンせよとのこと。
そうするとコンパイルできた。


Arduinoを用いたテンパー炉、リフロー炉の温度制御装置(2) (K型熱電対アンプモジュールでの温度測定編)

前回の教訓より、秋月電子のMAX31855使用 K型熱電対アンプモジュールを購入。
秋月電子の通販は朝に注文すれば翌日朝には届くので便利です。
けど、いくら買っても送料がかかる。
つい余計なものをいろいろ買って送料を浮かせたいという衝動に駆られ、今回もいろいろ買ってしまった。
ひとつはArduino uno 純正品です。
Arduino uno 届いたのみたら、チッちゃ。
いわれて見ればそのサイズなんだけど。
箱がキャラメル箱の少し多きいくらいでちょっとびっくり。
想像ではPCのマザボの小さいくらいのケースだとおもってたんが。

けど基板のデザインがかっこいい。ちょっとハイソな気分。

よくわからないけど、純正品でないとArduinoといってはいけないとか。
ブログタイトルが”Arduinoを用いた”とあるので、いちお写真のすみっこにいれておこう。


さて、本題です。
MAX31855使用 K型熱電対アンプモジュール届きましたが秋月にしては珍しく説明書がなかった。
早速、純正モデル君の出番。
参考ページのAdafruit Industries(エイダフルート)のリンクを見たが、回路図が無くて、よくわからんぞ。

なので、スイッチサイエンス様の

MAX31855 K型熱電対温度センサ 5V版(SPI接続)

を参照する。

しかし、秋月のモジュールは 通信形式:3線式出力専用SPIとのことですが、基板のシルクにDO,CS,CLKとある。
上記スイッチサイエンスのサイトや Maxim社のMAX31855 データシートでは MISO、SCK、SSの記述。


大体想像つきそうですが、ICのデータシートより、モジュールのICの足ピンからのパターンを追って
DO, → MISO
CS, → SS
CLK、→ SCK 
のようです。

で配線しました。
スケッチはスイッチサイエンスのをコピペ。
が、ちょっとはまりました。


・はまり一
 モジュールに近い0ピンでグランド取りたいので
  pinMode(0, OUTPUT);
  digitalWrite(0, LOW); 
 としましたがグランドにならなかった。
 深く考えずにモジュールまでグランド線を引っ張った。
実はデジタル0,1ピンはシリアル通信用に使用してるとのことで、使えないことが判明。素人だ。





・はまり二
モジュールに近い4ピンからSPI通信したく

#define SLAVE 4
  pinMode(SLAVE, OUTPUT);
  digitalWrite(SLAVE, HIGH);


とすれば 
 4(SS)、5(MOSI)、6(MISO)、7(SCK)
 になると思ったが、つないだら0度表示でたまにエラー。
又誤配線かと何度か配線しなおし。

答えは Arduino 日本語リファレンス 【SPIの概要】 にあった。

【接続】 SPI通信で使われるピンは次のとおりです。 
Arduino Duemilanove(ATmega168/328を搭載するボード): 10(SS)、11(MOSI)、12(MISO)、13(SCK) 

ということで、11,12,13は不動なのね。まぁそうだよな。
接続しなおしたらOKだった。 よかった。

早速、液晶のライブラリ入れて、修正してテスタの温度計と比較。


大体10度くらいの誤差。センサの位置が同じところにないせいだと思われる。

モジュールの方は室温も計っており、いわゆる冷接点温度補正をしています。
室温も表示できます。

とりあえず、温度測定は可能になった。
ソリッド・ステート・リレー(SSR)キット 25A(20A)タイプ
PID温度制御してみます。