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();
  }
}

0 件のコメント:

コメントを投稿