goo blog サービス終了のお知らせ 

もんく [とある南端港街の住人になった人]

スペインかポルトガルの港町に住みたい
日本→インドネシア→台湾→マレーシア→日本
since Oct. 2004

オシロスコープ買っちゃった

2017-05-31 21:41:47 | ABCのAはArduinoのA
アリババでオシロスコープを買ってみた。もちろんまだオーダーしただけなので来てはいないけれど。

価格は日本円にして約2万5千円。日本のアマゾンで買うより1万円から2万円安い。しかも送料無料。送料って言っても国内送料じゃなくて国際宅配送料なのがすごい。楽しみだ。

仕様は普通。70MHz版だともう少し安いけれどあまり違わないので100MHzを選んでおいた。テキトーだ。これを超えるとずっとずっと高くなるし、ネットで調べるとこのあたりでも使えるとの事だったのでこれにした。


オシロスコープ、大学の時にちょっと使ったか使わないか程度しか知らない、実を言うと。まあ、単なる計測器なので、しかも最近の製品でデジタルだから難しくは無いと思う。実際は何かノウハウってあるのか?

↑本体だけと書いているけど、付属品のプローブ等一式はもちろん付属します。

昔々、その昔、オシロスコープってのはものすごい高いもので個人で買うなんて考えられない物だった。買えないと思っていたから値段なんてよく知らなかったけれど、多分50万円とか70万円、そんな値段だったんじゃないかなあ。現実的に買えそうなのと言えば秋葉原でホコリかぶった中古品がけっこう出ていて、そんなものしか無かった。けれどそんなの誰が買うの?、インテリア?、骨董?、と言う状態だったのを思い出す。

それが今は中高生のお小遣いで新品が買えてしまうのだからビックリ。中国製だけれど。いや、中国製だからかな?


さあ、メイドイン中国のオシロスコープ、いつ来るんだろうか?

オシロスコープ買いたい

2017-05-30 23:59:59 | ABCのAはArduinoのA
デジタルな温度計、物自体は完成した。そしてマシンに取り付ける。動いた。なーんだ簡単じゃないか、と思った矢先、マシンが動き出すと温度表示ができなくなった。-127℃、センサーが接続されていない時と同じ状態になってしまう。

最初に買っていたセンサー4個では大丈夫だったらしい。9個接続してマシンが動くとダメ。なのでまず、信号線の根元に100Ωを入れてみた。これはセンサーが多数になった時はこうしろとどこかに書いてあったから。(実際にやってみた人は見つけられなかった。)果たして、数個は救われた。が、完全ではない。

次には電源をACアダプタからスマホの補助電池に交換。するとちゃんと表示はする。さて、このまま電池駆動と言うのはちょっとどうかと思う。やっても良いけれど。

もし電池駆動にするとしたら温度測りたい時だけONにすれば可能だろう。どうせそんなに頻繁に見る必要なんてない。が、一応それは最終手段としておこう。今は電源でちゃんと表示できるようにしないと。

この問題、また明日継続して調査する事にするが、どうしても手探りでしかできないのは歯痒い。せめてオシロスコープがあれば.......

そうだ、買おう。

値段調べ。
マレーシアのLelong.my..... そもそも安いキットと高い本格的っぽい(あくまでも「っぽい」)のしか売ってない。日本のAmazon.... けっこういろいろある。良いかもしれない。 中国のAliExpress...... あるある、日本Amazonと同じモデルが。値段、日本の半額までは行かないがそれに近い価格。それにDHL送料無料みたいなのもある。DHLならいつものように半月以上待つって事はないはず。早速選びに入ろう。


Hantek DSO5102Pあたりが早くも有力候補。USD250弱で送料込み、プローブ等一式揃えられる。サンプリングは100MHzと、多分Arduinoとか電源系を見るには十分と思われる。思われる...だけで何の確証もないが、一般的にはこの程度らしいとAmazonのコメントでは読める。

同じく中国メーカー製RIGOL、これも良さそうだけれど、ちょっと高い。どうなんだろう? それならあとちょっと出せばTechtronicsの安いモデルが買えそう。

やはり中国製のOWONは誰かがブログで中身の配線などが汚いと買いていたので却下。その他ポータブルな安いのも良さそうに見えるけれど、ゼロ点から合わせてないとか不安材料があるらしい。そうするとやはり最初の候補Hantekなのかな?

もうちょっと調べて明日にでも買ってみよう。
.....会社に請求できるか?

デジタルな温度計 その3

2017-05-28 22:27:33 | ABCのAはArduinoのA
休みの日の過ごし方、こう言うのをやってるとちょっと問題あるかもしれない。仕事の延長と言えば言えない事もなく、たまにどこか行こうかとも思うけれど、これやり始めるとけっこう時間がかかる。

今回は前回と同じ物の2個目だから前よりはずっと短時間でできた。それでもちょっとつまずいてしまったのでタイムロスがあった。その原因は1号機を作った時にLCDのコントラストのための入力を電圧の高い方か低い方か記録していなかった事による。


何と無く絶対高い方だと思い込んで作ってしまったら、LCDに何も出てこなくてどこか別の配線ミス、またはハンダの下手さから来ているのかと思ってしまった。単にコントラストの設定ミスだったのに。

コントラストは通常可変抵抗器で調整するのだけれど、一度決まればあとは文字が読めれば良いだけなので固定抵抗で分圧して代用している。可変抵抗器で調整した後に中央でどの程度の抵抗値になるかテスターでチェック。似たような分配比率になるように持っている抵抗器で分圧した。高い方が4.7kオームx2個、低い方は1kΩ。低い方の端をGNDにして高い方の端を5V、中央はLCDの右から3つ目に接続。

これで文字が読めるようになったのでここはこれ以上深追いせず、これでOKと言う事にする。

テストして何と無く表示するようなのでこのプロジェクトはここで終わりになると思う。詳細知りたい人は前の記事にスケッチなどあるので参照ください。

デジタルな温度計 その2

2017-05-22 22:39:03 | ABCのAはArduinoのA
動作確認が実機でできた。60mのいい加減な電線の先にセンサーを取り付けて温度表示ができたので基板を作ってみた。半田付けが結構たいへんだった。特にLCDの足のところが。

LCDには元から♂ピンが付いていた。そのままブレッドボードでテストするには良いのだけれど、ユニバーサル基板で表裏に部品を実装するときには半田付けに工夫が要る。今回がは裏面にピンを立ててArduiniの背中に乗せる事にしたのでLCDをその反対面に置くとLCDのピンが出た先は基板に銅箔が無い。どうしても表面で半田付けしないといけない。

なのでLCDのピンを直角に折り曲げて表面で半田付けする事にした。足が密集していて半田付けし辛い。出来上がりが汚くなった。やり直しが結構多くなったので半田の使用量も想像以上になってしまい、途中で買いに出た。


さて、面倒だけれど、これもう1セット作らなきゃいけないんだな....
パーツ買わないと.....
半田付けで苦労しないで良いやり方考えないと...

インストールしたスケッチは基本的に変更していない。シリアル通信部分をコメントアウトしただけ。
そうそう、LCDのコントラスト調整用10kΩボリュームは適当な固定抵抗で振り分けて調整無用にしてある。

デジタルな温度計 その1 (修正あり)

2017-05-13 23:59:59 | ABCのAはArduinoのA
金曜の夜はYoutubeではっぴーえんど(NHKの番組)を見てその次に再結成ライブ映像も見ていたので寝るのが遅くなってしまった。昼頃にクリニックに行って月末の狂犬病の予防注射の予約と書類記入の確認をしてもらう。(自分のじゃなくて猫たちのため) その後、昼過ぎになって頭がちょっとズキンズキンとして来るとともに眠くなって寝た。寝不足の症状。起きたのは何時か覚えていないけれど午後だ。

思い立って先日買った温度センサーを試してみる事にした。DS18B20と言うセンサーだ。世の中にはとてもクールでスマートなデバイスがあるもので、何とこの温度センサー、デジタル信号を直接送ってくる。今時そんな物が簡単に通販で手に入る。しかも中国製だって! 値段はRM9.9/1個(260円ほど)。何て世の中になったんだ!(文章じゃわかりにくいと思うが驚いてしかも感動していると思ってほしい。→ "!")

温度を測ると言えば、すぐに思いつくのは熱電対、サーミスタ、測温抵抗体、それに最近はアナログ電圧を送ってくるICもある。が、これはデジタル信号を送ってくると言うのだからビックリ。熱電対は出てくる電圧が小さいのでArduinoに直接つなげられないし、測温抵抗体もブリッジみたいにして途中の電線の長さを補償しないといけない。サーミスタやIC式だと使いやすいけれど配線が長かったりコネクタが入った時などにホントにその温度で合ってるの?と言う部分をどうにかしないといけない。が、(何度も言うけれど)このDS18B20はデジタル信号で来る。こりゃすごい、面白い、面白い、素晴らしい(かもしれない)じゃないか!


と言うわけで使ってみるのだけれど、早速これを使う用途と言うのがある。工場の作業員が温度計を持って歩いて定期的に、それもかなり頻繁に温度をチェックしないといけない部分があるからだ。早い話がセンサーを各所に設置して中央に表示しておきたい。(簡単な希望だと思う。)


さてこのDS18B20、使うにはセンサー自体が持つIDを調べないといけない。調べるにはArduinoに繋いで調べるプログラムを動かす。下のスケッチはネットで他人にいただいたもの。だからあまり深く考えないでそのまま使う。何しろ単に素子のIDがわかればそれで良いのだから。

接続は10番ピンにしてみた。
(先にOneWireのライブラリーをダウンロードしておく。)



-------------------------------------------------------

/This sketch is for detection of DS18B20 sensor serial number only

//Connect 1pc of DS18B20 on No.10 pin of UNO.
//Install this sketch on UNO.
//Open serial monitor on PC.
//Check number, take note and put a label on the sensor.

#include
const byte ONEWIRE_PIN = 10; //Connect DS18B20 on No.10 pin
OneWire onewire(ONEWIRE_PIN);
void setup()
{
while(!Serial);
Serial.begin(9600);
}
void loop()
{
byte address[8];

onewire.reset_search();
while(onewire.search(address))
{
if (address[0] != 0x28)
continue;

if (OneWire::crc8(address, 7) != address[7])
{
Serial.println(F("ERROR Not detected"));
break;
}
for (byte i=0; i<8; i++)
{
Serial.print(F("0x"));
Serial.print(address[i], HEX);
if (i< 7)
Serial.print(F(", "));
}
Serial.println();
}
while(1);
}


-------------------------------------------------------

1個繋いではシリアルモニタで確認、メモしてセンサーにタグを付けて置く。


次いでは接続図。
16x2のLCDに表示するようにしてある。
今のところDS18B20は4個接続している。
なぜなら通販で買った時に見せに在庫がそれしか無かったから。
本当はあと5個足して9個にしたい。
スケッチは9個仕様になっている。


上の図に間違いがあったので下のように修正。(2017/5/21)



スケッチはこんな感じ。
DeviceAddressのところはちゃんと9個あるけれど、良く見ると上の4つのセンサーのIDが繰り返し使われているだけ。また5個買ったらここは変更する予定。

-------------------------------------------------------

//Temp. checking with DS18B20 sensors

//DB12B20 section
#include       //ダウンロードしておく。(ライブラリ)
#include  //これもダウンロードしておく。(ライブラリ)

//LCD section
#include    //LCD用 (ライブラリ)

LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //LCDのピン番号


#define ONE_WIRE_BUS 10 //input pin No.
#define SENSER_BIT 9 //センサーの分解能を指定している。無くても可。

OneWire oneWire(ONE_WIRE_BUS); //おまじない
DallasTemperature sensors(&oneWire); //おまじない

DeviceAddress t1D1Z = { 0x28, 0xFF, 0x4A, 0xDE, 0x93, 0x16, 0x5, 0xBD };
DeviceAddress t1D2Z = { 0x28, 0xFF, 0x89, 0x28, 0x94, 0x16, 0x5, 0xD3 };
DeviceAddress t2D1Z = { 0x28, 0xFF, 0xC7, 0xE0, 0x93, 0x16, 0x5, 0xC7 };
DeviceAddress t2D2Z = { 0x28, 0xFF, 0xFF, 0x40, 0x8C, 0x16, 0x3, 0x1C };
DeviceAddress t3D1Z = { 0x28, 0xFF, 0x4A, 0xDE, 0x93, 0x16, 0x5, 0xBD };
DeviceAddress t3D2Z = { 0x28, 0xFF, 0x89, 0x28, 0x94, 0x16, 0x5, 0xD3 };
DeviceAddress t4D1Z = { 0x28, 0xFF, 0xC7, 0xE0, 0x93, 0x16, 0x5, 0xC7 };
DeviceAddress t4D2Z = { 0x28, 0xFF, 0xFF, 0x40, 0x8C, 0x16, 0x3, 0x1C };
DeviceAddress t4D3Z = { 0x28, 0xFF, 0xFF, 0x40, 0x8C, 0x16, 0x3, 0x1C };

void setup(void) {

//LCD initialize
lcd.begin(16, 2); //16 Char. x 2 Lines
lcd.clear(); //Clear screen
lcd.setCursor(0, 0); //Primary position
lcd.print("Start"); //Show "Start"
delay(1000);
lcd.clear(); //Clear screen

//Serial for Debug
Serial.begin(9600); //デバッグ用

//DB18B20 initialize
sensors.setResolution(SENSER_BIT);
sensors.begin();

}

void loop(void) {

//1D (LCDが2行しか表示しないのでセクションに分けている)
lcd.setCursor(0,0);
lcd.print("1D");
delay(1000);
lcd.clear();

sensors.requestTemperatures(); //温度を見に行っている

Serial.print("1D1Z=");
Serial.println(sensors.getTempC(t1D1Z)); //シリアルモニタに温度表示
lcd.setCursor(0,0);           //こちらはLCDに同じ事を表示
lcd.print("1D1Z=");
lcd.print(sensors.getTempC(t1D1Z));
delay(1000);

sensors.requestTemperatures();

Serial.print("1D2Z=");
Serial.println(sensors.getTempC(t1D2Z));
lcd.setCursor(0,1);
lcd.print("1D2Z=");
lcd.print(sensors.getTempC(t1D2Z));
delay(5000);
lcd.clear();

//2D
lcd.setCursor(0,0);
lcd.print("2D");
delay(1000);
lcd.clear();

sensors.requestTemperatures();

Serial.print("2D1Z=");
Serial.println(sensors.getTempC(t2D1Z));
lcd.setCursor(0,0);
lcd.print("2D1Z=");
lcd.print(sensors.getTempC(t2D1Z));
delay(1000);

sensors.requestTemperatures();

Serial.print("2D2Z=");
Serial.println(sensors.getTempC(t2D2Z));
lcd.setCursor(0,1);
lcd.print("2D2Z=");
lcd.print(sensors.getTempC(t2D2Z));
delay(5000);
lcd.clear();

//3D
lcd.setCursor(0,0);
lcd.print("3D");
delay(1000);
lcd.clear();

sensors.requestTemperatures();

Serial.print("3D1Z=");
Serial.println(sensors.getTempC(t3D1Z));
lcd.setCursor(0,0);
lcd.print("3D1Z=");
lcd.print(sensors.getTempC(t3D1Z));
delay(1000);

sensors.requestTemperatures();

Serial.print("3D2Z=");
Serial.println(sensors.getTempC(t3D2Z));
lcd.setCursor(0,1);
lcd.print("3D2Z=");
lcd.print(sensors.getTempC(t3D2Z));
delay(5000);
lcd.clear();

//4D-1
lcd.setCursor(0,0);
lcd.print("4D");
delay(1000);
lcd.clear();

sensors.requestTemperatures();

Serial.print("4D1Z=");
Serial.println(sensors.getTempC(t3D1Z));
lcd.setCursor(0,0);
lcd.print("4D1Z=");
lcd.print(sensors.getTempC(t3D1Z));
delay(1000);

sensors.requestTemperatures();

Serial.print("4D2Z=");
Serial.println(sensors.getTempC(t3D2Z));
lcd.setCursor(0,1);
lcd.print("4D2Z=");
lcd.print(sensors.getTempC(t3D2Z));
delay(5000);
lcd.clear();

//4D-2

sensors.requestTemperatures();

Serial.print("4D3Z=");
Serial.println(sensors.getTempC(t4D3Z));
lcd.setCursor(0,0);
lcd.print("4D3Z=");
lcd.print(sensors.getTempC(t4D3Z));
delay(5000);
lcd.clear();


Serial.println();
}


-------------------------------------------------------


Serial.xxxの行はデバッグ用なので走らせる時には消してもOK。


sensors.requestTemperatures();
↑この行を各所に入れているのは、できるだけ最新の温度を表示したいため。
ただ、リアルタイムで大きく変化する温度を想定していないので所々にdelayを入れている。作業員が見てメモできるようにしたいため。


初心者らしい間違いをしてしまった点。

DeviceAddress t1D1Z ←ここで最初に1D1Zのように数字で始まる変数を書いてしまった。こうするとエラーが出る。リファレンスを見るとちゃんと数字で始まる変数は止めろと一番最後の行に書いてあった。(基本的なところ、ちゃんと読めと言う事らしい。)

なので頭にtを付けておいた。
変数の記号、1D1Zとか2D2Zとかにしているのは単にセンサーを設置する場所を示しているだけなのでこれは自分の都合で変更して欲しい。(だれもマネしないだろうけれど。)



さて、ここまででプロトタイプその1は完成とします。
後は実際に電線を伸ばしていってノイズの影響などがあるかチェックの予定。

液面維持システム その9 強制給液ボタン追加など

2017-03-09 13:58:29 | ABCのAはArduinoのA
せっかく書いた記事(と言っても短い)がArduinoのスケッチを
貼り付けたせいで消えてしまった。
いつも同じ事をしているはずなのに、なぜなんだ?

仕方ないのでこのWebサービスを使わせていただいた。
ソースコード変換


本題に入ります。
ブログに乗せる頻度より更新の頻度が高くて前回と話がつながらないかもしれない。

あれから変えたところ。

1.強制給液ボタンを追加。
 
あると便利で手で溶剤を扱う必要が減る。
また何か問題が起きたときにこれが使えると咄嗟にリカバリできるかもしれない。
できないかもしれないが。

このボタンはNO(ノーマルOpen)。

リセットがでLED点滅サブルーチンに強制給液の動作を追加した。
リセットボタンと同時に強制ボタンを押していると給液する。
ボタンを離すと止まる。レベルセンサーでの停止はない。
その後に通常リセットと同じで待ち時間に入ると言う動作。


2.リセットスイッチはNC(ノーマルClose)にした。

機能的にはどっちでも良いけれど、
その方が誤動作が少なそうだから。
電池でやるわけでもないので消費電力を気にする事もないし。

3.リセットスイッチのチャタリング防止を止めた。

何か効かなそうだから。
割り込みのサブルーチンに時間管理関係の命令が入っていたので。
(他の人の例で見たので使っていたが...)

4.リセットスイッチは長押しでリセットになるようにした。

誤動作防止のため。

5.待ち時間の最後にLEDの鼓動が速くなるようにした。

作業する人がわかるように。



間違えたところ。

リセットした時にReset0のフラグを立てるが、
それをLEDの長点灯と強制給液のサブルーチンの最後のところで
キャンセルしなかったので
プログラムの2順目になると処理速度が2倍位になってしまった。
Reset0をキャンセルしておかないと余計なところに迷い込んでしまうのだった。

ノイズでArduinoが何か影響受けているか
壊れたかと思った。

どうしてわかったかと言うと以前に問題なかったスケッチを入れなおしたら
元に戻ったから。







//Timer setting
int TimeW = 1; //Waiting time in minutes (1 = 1min)
int TimeP = 120; //Max. pumping time to detect error (1 = 1sec)


//PUMP manual ON button is added (from Rev. 13)
//Push RESET first, then push PUMP button.
//Pumping starts. When button released, pump stops.

//---------no need to change-------------

//INPUT PIN number
int LVS = 2; //Level sensor pin number
int RSS = 3; //Reset switch number
int PUM = 8; //Pump (Relay) ON switch number (from Rev13)

//OUTPUT PIN number
int RUN = 4; //RUN indication LED
int ERR1 = 5; //ERROR indication LED1
int ERR2 = 6; //ERROR indication LED2
int Valve = 7; //Relay for air valve



//For interrupt (input)
volatile int Reset0 = LOW; //RSS switch initial status
int Reset = LOW; //Reset flug for main program

//For liquid level checking
int Level = LOW; //Valve initial status


//Anti-chattering function
volatile int bounceR = 100;
volatile int ctR;
volatile int ptR = 0;




void setup() {

  //Debug only 1/9
  //Serial.begin(9600);

  //OUTPUT PIN
  pinMode(RUN, OUTPUT);   //RUN indication LED
  pinMode(ERR1, OUTPUT);  //ERROR indication LED1
  pinMode(ERR2, OUTPUT);  //ERROR indication LED2
  pinMode(Valve, OUTPUT); //Relay for air valve

  //INPUT PIN
  pinMode(LVS, INPUT); //Low level is NC (Normal 0V)
  pinMode(RSS, INPUT); //Switch is NC (Normal 0V)
  pinMode(PUM, INPUT); //Switch is NO (Normal 5V)

  //INTERRUPT
  attachInterrupt(digitalPinToInterrupt(RSS), RESET, FALLING); //Switch is NC

}

void loop() {

  //Debug only 2/9
  //Serial.println("Start");
  //Serial.print(" Reset=");
  //Serial.println(Reset);
  
  //Counting wating time to pump ON------------------
  
  Reset = LOW;           //Cancel reset flag to start
  while(Reset == LOW) {  //If Reset become 1, return to beginning

    //Debug only 3/9
    //Serial.println("Waiting start");

    digitalWrite(Valve, LOW);  //Valve close
    digitalWrite(RUN, LOW);    //RUN LED reset
    digitalWrite(ERR1, LOW);   //ERR1 LED reset
    digitalWrite(ERR2, LOW);   //ERR2 LED reset
    
    int varW = 0;
    while(varW < TimeW && Reset == LOW){ //time timer in min. If Reset pushed, stop waiting
      int varW0 = 0;
      while(varW0 <= 60 && Reset == LOW){ //1min timer. If Reset pushed, stop waiting
        digitalWrite(RUN, HIGH);  //Flash while waiting 0.5sec ON - 0.5sec OFF
        delay(100);
        digitalWrite(RUN, LOW);
        delay(900);
        if(Reset0 == HIGH){
          RESFLASH(); //If Reset 3 LEDs Flash
        }
        varW0++;
      }
      varW++;
      if(varW == TimeW && Reset == LOW){   //RUN LED flickering when time up
        int flick = 0;
        while(flick <= 10){
          digitalWrite(RUN, HIGH);
          delay(200);
          digitalWrite(RUN, LOW);
          delay(200);
          flick++;
        }
      }

      //Debug only 4/9
      //Serial.print(varW);
      //Serial.println("min");
    }
  
    //Start pumping------------------

    //Debug only 5/9
    //Serial.println("Pumping start");
    //Serial.print("Level sensor =" );
    //Serial.println(Level);

    Level = 0;     //Level initialize
    int varP = 0;  //Time initialize
    int Lev0 = 0;  //Level status1
    int Lev1 = 0;  //Level status2
    int Lev2 = 0;  //Level status3
    int LStat = 0; //Total status
    
    while(varP < TimeP && Level == 0 && Reset == LOW) { //Pumping when Low-level, Reset is LOW
      
      Lev0 = digitalRead(LVS);   //check liquid level HIGH or LOW
      if(Lev0 == LOW){           //Liquid level High = LOW
        LStat = 1;
        delay(500);
        Lev1 = digitalRead(LVS); //Chatering proof 2nd check
        if(Lev1 == LOW){
          LStat++;
        }
        delay(500);
        Lev2 = digitalRead(LVS);
        if(Lev2 == LOW){
          LStat++;
        }
        if(LStat == 3 || Lev2 == HIGH){
          Level = 1;
        }
      }else{
        digitalWrite(Valve, HIGH); //Air valve OPEN
        digitalWrite(RUN, HIGH); //RUN LED light
        delay(1000);
      }

       if(Reset0 == HIGH){
          RESFLASH(); //If Reset 3 LEDs Flash
        }
      varP++;

      //Debug only 6/9
      //Serial.println(varP);
      //Serial.print("Level Sensor check = ");
      //Serial.println(Level);

    }

    
    //Stop pumping-----------------------

    //Debug only 7/9
    //Serial.println("Stop pumping");
    //Serial.print("Level Sensor = ");
    //Serial.println(Level);

    digitalWrite(Valve, LOW); //Pumping stop, reached on max time
    digitalWrite(RUN, LOW);   //RUN LED dark
    delay(1000);

    
    if(Level == 0 && Reset == LOW){
      while(Reset == LOW){        //Error TimeUp, waiting for Manual RESET
        digitalWrite(ERR1, HIGH); //LED1 ON-OFF
        digitalWrite(ERR2, LOW);  //LED2 ON-OFF
        delay(500); //Waiting for RESET SWITCH
        digitalWrite(ERR1, LOW);
        digitalWrite(ERR2, HIGH);
        delay(500);

        if(Reset0 == HIGH){
          RESFLASH(); //If Reset 3 LEDs Flash
        }

        //Debug only 8/9
        //Serial.println("TimeUP");
      }
      digitalWrite(ERR1, LOW); //ERR LED1 Cancel
      digitalWrite(ERR2, LOW); //ERR LED2 Cancel

      //Debug only 9/9
      //Serial.println("RESET");
    }
    
  } //If reset SW is ON, return to beginning
}


void RESET() {  //Interrupt for RESET
    Reset0 = HIGH; //When push RSS
}


void RESFLASH() {  //RESET re-confirmation and Indication
  int Reset1 = HIGH; //Switch is NC
  int Reset2 = HIGH;
  int Pump = LOW;

  delay(1000);
  Reset1 = digitalRead(RSS); //Long-push requred to confirm RESET
  delay(1000);
  Reset2 = digitalRead(RSS);
  
  Pump = digitalRead(PUM);   //Pump manual ON
  while(Pump == HIGH){
    digitalWrite(Valve, HIGH);
    digitalWrite(RUN, HIGH);
    Pump = digitalRead(PUM);
    delay(500);
  }

  digitalWrite(Valve, LOW);

  if(Reset1 == LOW && Reset2 == LOW){ //RESET indication
    digitalWrite(ERR1, HIGH);
    digitalWrite(ERR2, HIGH);
    digitalWrite(RUN, HIGH);
    delay(2000);
    digitalWrite(ERR1, LOW);
    digitalWrite(ERR2, LOW);
    digitalWrite(RUN, LOW);
      
    Reset = HIGH;
    Reset0 = LOW;  //RESET (1st signal) reset to initial
  }
}
</code>

液面維持システム その8 ノイズ対策(割込み禁止で重要な事、追記)

2017-03-05 23:29:36 | ABCのAはArduinoのA
家でやると上手く行くのに
実機では上手く動かない。

その原因が内蔵プルアップにあると思って
外部プルアップに変更していた。
それで行けるんだろうな、と思ったのが2月25日。
液面維持システム その7で書いた。

が、その後、外部プルアップでやっても同じ事が起きるとわかった。
しかも、基板上のリセットスイッチ配線の端子にテスターやドライバーが触れるだけで
リセットがかかってしまう。
リセットは割り込みだからドライバーなどで触るといつでもリセット動作が起きる。
さらに、ソレノイドかリレーの開閉のタイミングにもリセットがかかる。

家と実機での違いは、リレーの先に電源に繋がったソレノイドバルブがあるか無いか。
こりゃもうわからん、と言うことで、
おしえてgooで質問させてもらったところ、ある方から回答を頂けた。

かいつまんで言うと、
ハイインピーダンスの入力に外部の誘導ノイズが乗っているのだろうと言う事。
そして対策はプルアップ抵抗と並列にコンデンサを付ける。



やってみた。
確かに効果あり。
端子にドライバーで触ってもリセットはしない。
(家に配線ごと全部持ち帰ってテスト。)

が、実機ではソレノイドバルブ開閉でリセットがかかる現象だけが残った。
そうだ、ソレノイドバルブの電源はAC220V。
これを直流の低い電圧の物に替えよう。

早速DC12Vのを買った。
コイルの接点両端をまたぐようにダイオードを取り付けた。



そしてリレーユニットを本体基板から外して別体化し
中国人からいただいたお茶の缶に入れた。

リレーユニットの入力と電源にも用心してダイオード設置。



少しはマシ。
でもまだソレノイドの動作があるところだけのリセットは残った。
しかも、このソレノイドバルブではダイヤフラムポンプを駆動するために
通せるエアの量がたりなかった。

と言うわけで、DC12Vソレノイドは却下。
DCアダプタと合わせて約RM80もしたのに....


写真はDC12Vソレノイドの時の構成。

それでAC220Vソレノイド戻して他の全ての配線もちょっといい加減だがシールドした。

さらに、スケッチもリレーのON-OFFの前後で割込リセットがかからないように変更。

と、それで結果は?
と言いたいところなのだが、ちゃんと動作試験ができていないので
残念ながらここに書く事ができない。

結果はまた次回報告。
スケッチは明日にでもこの下↓にコピーします。


-------------------スケッチ--------------------

スケッチを載せておこうと思ったけれど
その前に変更してしまったのでやめます。

1つだけ、大切な事がわかったので書きます。

"リレーのON-OFF前後で割込みがかからないように..."
noInterrupts()とinterrupts()でON-OFFの部分を囲んだ。
その中にdelay(1000)と1秒の待ち時間を入れた。

ところが、1秒カウントしてくれない。
さっさと過ぎてしまう。
確か割込みで飛んだ先のサブルーチンの中はそれができなかったはず。
でも、それ以外のところで時間カウントができないとは聞いていない。

が、よくよく調べると(リファレンスには書いてないが)
割込み禁止の中でも時間カウントができなくなるそうだ。
いろいろあるものだ。

---------------------------------------------------


ところで、次のプロジェクトは.......
フィルムの上に塗ったインクの量を透過光の量で測ってみようと言うもの。
CdS(LDR)を使ってフィルム裏から当てた透過光を数値化するつもり。

アイデアとしては、CdSを複数直列にして面内の平均値を(実際には合計値)検出。
そこから読んだ数値を16x2のLCDに表示する。
数字を読むだけだとわかりにくいので可変抵抗器を回して標準値を作り、
その標準値と現在値の違いをLCD上かLED、または両方同時にを使って
アナログ的にわかりやすく表示する。

問題点は、光源が耐久的にどれだけ信頼できるか。
光源は多分LEDだと思うが、その電源をどうするか。
CdSの耐久性はどう確保できるか。
のような事だと今は考えている。

また、できればロガーとして長時間記録できればなあとも思う。
Arduinoに慣れている人にとっては簡単な事の組み合わせなのかなと思うけれど...

液面維持システム その7 内蔵プルアップの罠(わな) ←記事に間違いあり注意

2017-02-25 18:08:18 | ABCのAはArduinoのA
※追記 (2017年3月2日)
この記事には間違いがありますのでそう思って読んでください。
間違いの内容はできるだけ早めに別記事で案内いたします。




前回、完成と思った。
なぜならブレッドボード上では完全に機能したから。

が、実際取り付けるべき場所に取り付けると上手くいかない。
症状はポンピングに進まないと言う事。

テスターで当たってみると、
リセットスイッチ周りがおかしい。
テスターのプローブをスイッチの端子に当てると
それだけでリセットがかかる。
端子台がダメなのか、端子台を熱でダメにしてしまったのか?

GNDと入力で抵抗を測ってみると、
あれっ?
導通がある。
数百Ωから千ちょっとΩ。
どこかおかしいのか?
と思ったが、どのピンでもそうだった。
そう言うものらしい。

じゃ、何がダメなのか?
と、気付いたのは内蔵プルアップを使って回路を組んでいる事。
内蔵プルアップを使うとArduinoの外に抵抗を付ける必要が無い。
つまりスイッチとArduinoのピンが直結だ。
その時、ピンに何かが触ってちょっとだけ電流が逃げるとする。
スイッチまでの配線が長くなっていてArduino流す電流はちょっとだけ。
そこに流れる電流がどこかに逃げたらスイッチがONだかOFFだか
してる事になりはしないか?
OFFのスイッチを経由しないでどこかでリークしてGNDに入ったと同じになる。



スケッチで内蔵プルアップを使って配線を横着したのまずかったか?
なので、ちゃんと外部プルアップに変更した。
4.7kΩでリセットスイッチ、液面センサーともにやってみた。



プルアップの変更のためにスケッチも変更した。
リセットスイッチは内蔵プルアップでRISINGだった。
これは文字通り押した時に感知するのではなくて、
押したのを離した時に感知するものだった。
どっちでも良いのだ。

なのでこれはこのままにして、
外部プルアップは押した時に感知する事にした。


逆に液面センサーはちゃんと論理逆転でHIGHでなくて
LOWで液面が高いと認識するように変更。
(センサーが逆論理になっているから、液面低でHIGH)


せっかくなので別件でもう1つ変更。

待ち時間に青LEDを点滅させるようにした。
これまでは何もせず時間待ちだったけれども、
それだと10分間、正しく動いているのか止まっているのかがわからなかった為。


箱も用意。
アイスクリームの箱に配線用の穴を開けて入れる事にした。


マレーシア場合、1kgだか1リットルだか、
そんな単位で平気でアイスクリームが売られているのだ。
暑いから? 家族が多いから? それとも単に甘いものが好きだから?



-------以下が最新スケッチ-------
(そのまま貼り付けているので見難くなっています。)



//Timer setting
int TimeW = 10; //Waiting time in minutes (1 = 1min)
int TimeP = 120; //Max. pumping time to detect error (1 = 1sec)


//---------no need to change-------------

//INPUT PIN number
int LVS = 2; //Level sensor pin number
int RSS = 3; //Reset switch number

//OUTPUT PIN number
int RUN = 4; //RUN indication LED
int ERR1 = 5; //ERROR indication LED1
int ERR2 = 6; //ERROR indication LED2
int Valve = 7; //Relay for air valve



//For interrupt (input)
volatile int Reset = LOW; //RSS switch initial status

//For liquid level checking
int Level = LOW; //Valve initial status


//Anti-chattering function
volatile int bounceR = 100;
volatile int ctR;
volatile int ptR = 0;




void setup() {

//Debug only 1/9
//Serial.begin(9600);

//OUTPUT PIN
pinMode(RUN, OUTPUT); //RUN indication LED
pinMode(ERR1, OUTPUT); //ERROR indication LED1
pinMode(ERR2, OUTPUT); //ERROR indication LED2
pinMode(Valve, OUTPUT); //Relay for air valve

//INPUT PIN
pinMode(LVS, INPUT); //Low level is HIGH- Normal HIGH
pinMode(RSS, INPUT); //Push is HIGH - NoromalLOW

//INTERRUPT
attachInterrupt(digitalPinToInterrupt(RSS), RESET, RISING);

//Level sensor Normal-ON type

}

void loop() {

//Debug only 2/9
//Serial.println("Start");
//Serial.print(" Reset=");
//Serial.println(Reset);

//Counting wating time to pump ON------------------

Reset = LOW; //Cancel reset flag to start
while(Reset == LOW) { //If Reset become 1, return to beginning

//Debug only 3/9
//Serial.println("Waiting start");

digitalWrite(Valve, LOW); //Valve close
digitalWrite(RUN, LOW); //RUN LED reset
digitalWrite(ERR1, LOW); //ERR1 LED reset
digitalWrite(ERR2, LOW); //ERR2 LED reset

int varW = 0;
while(varW < TimeW && Reset == LOW){ //time timer in min. If Reset pushed, stop waiting
int varW0 = 0;
while(varW0 <= 60 && Reset == LOW){ //1min timer. If Reset pushed, stop waiting
digitalWrite(RUN, HIGH); //ただの待ち時間だったところを点滅に変更。
delay(100);
digitalWrite(RUN, LOW);
delay(900);
if(Reset == HIGH){
RESFLASH(); //If Reset 3 LEDs Flash
}
varW0++;
}
varW++;

//Debug only 4/9
//Serial.print(varW);
//Serial.println("min");
}

//Start pumping------------------

//Debug only 5/9
//Serial.println("Pumping start");
//Serial.print("Level sensor =" );
//Serial.println(Level);

Level = 0; //Level initialize
int varP = 0; //Time initialize
int Lev0 = 0; //Level status1
int Lev1 = 0; //Level status2
int Lev2 = 0; //Level status3
int LStat = 0; //Total status

while(varP < TimeP && Level == 0 && Reset == LOW) { //Pumping when Low-level, Reset is LOW

Lev0 = digitalRead(LVS); //check liquid level HIGH or LOW
if(Lev0 == LOW){ //液面センサーの検出論理変更
LStat = 1;
delay(500);
Lev1 = digitalRead(LVS); //Chatering proof 2nd check
if(Lev1 == LOW){ //液面センサーの検出論理変更
LStat++;
}
delay(500);
Lev2 = digitalRead(LVS);
if(Lev2 == LOW){
LStat++;
}
if(LStat == 3 || Lev2 == HIGH){
Level = 1;
}
}else{
digitalWrite(Valve, HIGH); //Air valve OPEN
digitalWrite(RUN, HIGH); //RUN LED light
delay(1000);
}

if(Reset == HIGH){
RESFLASH(); //If Reset 3 LEDs Flash
}
varP++;

//Debug only 6/9
//Serial.println(varP);
//Serial.print("Level Sensor check = ");
//Serial.println(Level);

}


//Stop pumping-----------------------

//Debug only 7/9
//Serial.println("Stop pumping");
//Serial.print("Level Sensor = ");
//Serial.println(Level);

digitalWrite(Valve, LOW); //Pumping stop, reached on max time
digitalWrite(RUN, LOW); //RUN LED dark
if(Level == 0 && Reset == LOW){
while(Reset == LOW){ //Error TimeUp, waiting for Manual RESET
digitalWrite(ERR1, HIGH); //LED1 ON-OFF
digitalWrite(ERR2, LOW); //LED2 ON-OFF
delay(500); //Waiting for RESET SWITCH
digitalWrite(ERR1, LOW);
digitalWrite(ERR2, HIGH);
delay(500);

if(Reset == HIGH){
RESFLASH(); //If Reset 3 LEDs Flash
}

//Debug only 8/9
//Serial.println("TimeUP");
}
digitalWrite(ERR1, LOW); //ERR LED1 Cancel
digitalWrite(ERR2, LOW); //ERR LED2 Cancel

//Debug only 9/9
//Serial.println("RESET");
}

} //If reset SW is ON, return to beginning
}


void RESET() {
ctR = millis(); //Anti-chattering
if((ctR - ptR) > bounceR && ptR != 0){
Reset = HIGH; //When push RSS

}
ptR = ctR;
}


void RESFLASH() { //Indication for RESET
digitalWrite(ERR1, HIGH);
digitalWrite(ERR2, HIGH);
digitalWrite(RUN, HIGH);
delay(2000); //リセットでの点灯時間も1秒→2秒に変更。
digitalWrite(ERR1, LOW);
digitalWrite(ERR2, LOW);
digitalWrite(RUN, LOW);
}


液面維持システム その6 やっぱりポカミスあり

2017-02-20 13:27:21 | ABCのAはArduinoのA
昨日のスケッチ、やはりミスあり。
割込のサブルーチンの中では時間を扱う事ができないのに
delay()を入れていた。

これが入っていてどうなるかと言うと、
スケッチに従ってLED3つが点灯するも
delay()の中に書き込んだ1000msec(1秒)は無視される。
ちょっと点灯したかと思うとすぐ消える。


対策はLEDの点灯-消灯は別のサブルーチンで作り、
このサブルーチンが呼び出されるように必要各所にばらまいた。

アップロードすると上手く動く。
(下記スケッチ)



さて、ここでもう1つ、小さな問題が発生。

PCからアップロードした瞬間は上手く動く。
が、アップロードせずに電源供給のつもりでUSBケーブルをつなぐと
動きがおかしい。
なぜかリレーがONしたままになってそこから動かない。
リセットスイッチ(大きなスイッチ)を押しても何も起きない。
Arduinoのリセットスイッチもダメ。

つまりアップロードしたままにしないと動かない。
これは困る。
常にPCを繋げておくわけにはいかない。


が、原因がわかった。
USBから電源を入れているために
USBを接続するとArduinoが通信待ちになるらしい。
今、別電源がここにないので実証しにくいが、
PC側のUSBプラグをちょっと浮かして接続すると上手く動く事がわかった。

USBプラグの端子は最初に脇の部分にある電源が先に接触するようになっていて
中央のデータ通信部分はその後だ。
だから脇の電源ラインだけ接触した状態にすると通信は期待されない。

電源は街の携帯電話ショップかDIYショップにある
スマホ・チャージャーを使う予定なので
たぶん実機に取り付けた時には動きそうだ。




ところで、
Arduino、多少の慣れがあれば誰にでも作れるしプログラミングも簡単。
初心者キットなども簡単に手に入る。
面倒な回路を組まなくても接続するだけで動くモジュールもたくさんある。
つまり誰もがゼロからでも始められる。
ちょっと前に同じ事をやろうとしたらけっこうなマニアか技術屋さんで
パーツを買える店を秋葉原などで知っている人しかできなかった。
今は通販で中国から飛んでくる。
かなり安い物でも送料無料だったりする。
本当に良い時代。

これを昔みたいに三菱とかオムロンとかのPLCと
(知らない人は工業用コントローラーだと思ってください)
キーエンスやオムロンとかのセンサーなんかを高いお金を出して
専門の技術を学んだ人にやってもらわないといけなかった。
もちろんそっちにもメリットが多いのでそれが無くなるわけはないけれど

今はちょっとした事ならこうして数百円のArduinoでも簡単にできる。
PLCなんか使うと金額が大きくなり人も動くから
できるかどうかわからない事やテストなんかには使いにくい。
失敗できないから。

失敗できると言うのは強い。
カメラがフィルムに写して現像するのからデジタルになったら
失敗した写真は単純に消せば良いことになった。
それと似ている。

作っているのか、それとも失敗に慣れる練習しているのか?






//Timer setting
int TimeW = 1; //Waiting time in minutes (1 = 1min)
int TimeP = 120; //Max. pumping time to detect error (1 = 1sec)


//---------no need to change-------------

//INPUT PIN number
int LVS = 2; //Level sensor pin number
int RSS = 3; //Reset switch number

//OUTPUT PIN number
int RUN = 4; //RUN indication LED
int ERR1 = 5; //ERROR indication LED1
int ERR2 = 6; //ERROR indication LED2
int Valve = 7; //Relay for air valve



//For interrupt (input)
volatile int Reset = LOW; //RSS switch initial status

//For liquid level checking
int Level = LOW; //Valve initial status


//Anti-chattering function
volatile int bounceR = 100;
volatile int ctR;
volatile int ptR = 0;




void setup() {

//Debug only 1/9
Serial.begin(9600);

//OUTPUT PIN
pinMode(RUN, OUTPUT); //RUN indication LED
pinMode(ERR1, OUTPUT); //ERROR indication LED1
pinMode(ERR2, OUTPUT); //ERROR indication LED2
pinMode(Valve, OUTPUT); //Relay for air valve

//INPUT PIN
pinMode(LVS, INPUT_PULLUP);
pinMode(RSS, INPUT_PULLUP);

//INTERRUPT
attachInterrupt(digitalPinToInterrupt(RSS), RESET, RISING);

//Level sensor Normal-ON type

}

void loop() {

//Debug only 2/9
Serial.println("Start");
Serial.print("Reset=");
Serial.println(Reset);

//Counting wating time to pump ON------------------

Reset = LOW; //Cancel reset flag to start
while(Reset == LOW) { //If Reset become 1, return to beginning

//Debug only 3/9
Serial.println("Waiting start");

digitalWrite(Valve, LOW); //Valve close
digitalWrite(RUN, LOW); //RUN LED reset
digitalWrite(ERR1, LOW); //ERR1 LED reset
digitalWrite(ERR2, LOW); //ERR2 LED reset

int varW = 0;
while(varW < TimeW && Reset == LOW){ //time timer in min. If Reset pushed, stop waiting
int varW0 = 0;
while(varW0 <= 60 && Reset == LOW){ //1min timer. If Reset pushed, stop waiting
delay(1000);
if(Reset == HIGH){
RESFLASH(); //If Reset 3 LEDs Flash
}
varW0++;
}
varW++;

//Debug only 4/9
Serial.print(varW);
Serial.println("min");
}

//Start pumping------------------

//Debug only 5/9
Serial.println("Pumping start");
Serial.print("Level sensor =" );
Serial.println(Level);

Level = 0; //Level initialize
int varP = 0; //Time initialize
int Lev0 = 0; //Level status1
int Lev1 = 0; //Level status2
int Lev2 = 0; //Level status3
int LStat = 0; //Total status

while(varP < TimeP && Level == 0 && Reset == LOW) { //Pumping when Low-level, Reset is LOW

Lev0 = digitalRead(LVS); //check liquid level HIGH or LOW
if(Lev0 == HIGH){
LStat = 1;
delay(500);
Lev1 = digitalRead(LVS);
if(Lev1 == HIGH){
LStat++;
}
delay(500);
Lev2 = digitalRead(LVS);
if(Lev2 == HIGH){
LStat++;
}
if(LStat == 3 || Lev2 == HIGH){
Level = 1;
}
}else{
digitalWrite(Valve, HIGH); //Air valve OPEN
digitalWrite(RUN, HIGH); //RUN LED light
LStat = 0; //LStat reset
delay(1000);
}

if(Reset == HIGH){
RESFLASH(); //If Reset 3 LEDs Flash
}
varP++;

//Debug only 6/9
Serial.println(varP);
Serial.print("Level Sensor check = ");
Serial.println(Level);

}


//Stop pumping-----------------------

//Debug only 7/9
Serial.println("Stop pumping");
Serial.print("Level Sensor = ");
Serial.println(Level);

digitalWrite(Valve, LOW); //Pumping stop, reached on max time
digitalWrite(RUN, LOW); //RUN LED dark
if(Level == 0 && Reset == LOW){
while(Reset == LOW){ //Error TimeUp, waiting for Manual RESET
digitalWrite(ERR1, HIGH); //LED1 ON-OFF
digitalWrite(ERR2, LOW); //LED2 ON-OFF
delay(500); //Waiting for RESET SWITCH
digitalWrite(ERR1, LOW);
digitalWrite(ERR2, HIGH);
delay(500);

if(Reset == HIGH){
RESFLASH(); //If Reset 3 LEDs Flash
}

//Debug only 8/9
Serial.println("TimeUP");
}
digitalWrite(ERR1, LOW); //ERR LED1 Cancel
digitalWrite(ERR2, LOW); //ERR LED2 Cancel

//Debug only 9/9
Serial.println("RESET");
}

} //If reset SW is ON, return to beginning
}


void RESET() {
ctR = millis(); //Anti-chattering
if((ctR - ptR) > bounceR && ptR != 0){
Reset = HIGH; //When push RSS

}
ptR = ctR;
}


void RESFLASH() { //Indication for RESET
digitalWrite(ERR1, HIGH);
digitalWrite(ERR2, HIGH);
digitalWrite(RUN, HIGH);
delay(1000);
digitalWrite(ERR1, LOW);
digitalWrite(ERR2, LOW);
digitalWrite(RUN, LOW);
}

液面維持システム その5

2017-02-19 23:55:54 | ABCのAはArduinoのA
昨日、Arduinoをアップデートして失敗し
結局元のバージョンに戻した。
それで確かにスケッチのアップロードは成功。

が、なぜか動きがダメ。
一体なぜなのか、と、いろいろ調べる。
あれっ、LEDの両端子が短絡している。
こっちのLEDもあっちのLEDも、
そして最後にはセンサーまで全部短絡していると判明。
どこかでハンダ付けを失敗しているのでは....???

1つ1つラインを外して見てみるが変わらず。
まさかと思い、基板上の関係無いはずの部分にテスターを当てる。
ここも短絡している!
なんだそりゃー?!
ハンダとも何の素子とも関係無いところがなぜ?

見た目は普通のユニバーサルPCBだが、
不良品なのか?
ちゃんとハンダ付け面にはドーナツがいくつもある。
わからん。
とりあえず全部短絡しているらしいが見た目はわからない。
中国製には時々こんなのがあるのか?
買い直さなければ。

それだけ買いに行くにも店は近くにない。
ここからPuduまではKLを抜けて行かないといけないので
ちょっと大変。

と言う事で、仕方なく以前に買った小さなユニバーサル基盤を使うことにした。
しかし半分程度の大きさなので面積が足りない。
なので2つ繋げて使う事にした。


写真左の黄色いLEDはダミーの負荷。
本来はここにエア用のソレノイドバルブ(200V仕様)が付く。


スケッチも少し改良。
1.リセットスイッチを押した時に3つのLEDが点灯して押した事がわかるようにした。
2.液面センサーのチャタリングを検知するようにした。
 最初に液面がセンサーのレベルまで来たら0.5秒毎にあと2回検出。
 3回ともONか、1回目と3回目がONとなっていたら液がそこにあるとした。

テストでは何となく思い通りに動いている感じがする。
(本当か?)

スケッチは以下。
(誰か間違っていると思ったら教えて下さい。)




//Timer setting
int TimeW = 1; //Waiting time in minutes (1 = 1min)本番は10分にする予定。
int TimeP = 120; //Max. pumping time to detect error (1 = 1sec)


//---------no need to change-------------

//INPUT PIN number
int LVS = 2; //Level sensor pin number
int RSS = 3; //Reset switch number

//OUTPUT PIN number
int RUN = 4; //RUN indication LED
int ERR1 = 5; //ERROR indication LED1
int ERR2 = 6; //ERROR indication LED2
int Valve = 7; //Relay for air valve



//For interrupt (input)
volatile int Reset = LOW; //RSS switch initial status

//For liquid level checking
int Level = LOW; //Valve initial status


//Anti-chattering function
volatile int bounceR = 100;
volatile int ctR;
volatile int ptR = 0;




void setup() {

//Debug only
//Serial.begin(9600);

//OUTPUT PIN
pinMode(RUN, OUTPUT); //RUN indication LED
pinMode(ERR1, OUTPUT); //ERROR indication LED1
pinMode(ERR2, OUTPUT); //ERROR indication LED2
pinMode(Valve, OUTPUT); //Relay for air valve

//INPUT PIN
pinMode(LVS, INPUT_PULLUP);
pinMode(RSS, INPUT_PULLUP);

//INTERRUPT
attachInterrupt(digitalPinToInterrupt(RSS), RESET, RISING);

//Level sensor Normal-ON type

}

void loop() {

//Debug only
//Serial.println("Start");
//Serial.print("Reset=");
//Serial.println(Reset);

//Counting wating time to pump ON------------------

Reset = LOW; //Cancel reset flag to start
while(Reset == LOW) { //If Reset become 1, return to beginning

//Debug only
//Serial.println("Waiting start");

digitalWrite(Valve, LOW); //Valve close
digitalWrite(RUN, LOW); //RUN LED reset
digitalWrite(ERR1, LOW); //ERR1 LED reset
digitalWrite(ERR2, LOW); //ERR2 LED reset

int varW = 0;
while(varW < TimeW && Reset == LOW){ //time timer in min. If Reset pushed, stop waiting
int varW0 = 0;
while(varW0 <= 60 && Reset == LOW){ //1min timer. If Reset pushed, stop waiting
delay(1000);
varW0++;
}
varW++;

//Debug only
//Serial.print(varW);
//Serial.println("min");
}

//Start pumping------------------

//Debug only
//Serial.println("Pumping start");
//Serial.print("Level sensor =" );
//Serial.println(Level);

Level = 0; //Level initialize
int varP = 0; //Time initialize
int Lev0 = 0; //Level status1
int Lev1 = 0; //Level status2
int Lev2 = 0; //Level status3
int LStat = 0; //Total status

while(varP < TimeP && Level == 0 && Reset == LOW) { //Pumping when Low-level, Reset is LOW

Lev0 = digitalRead(LVS); //check liquid level HIGH or LOW
if(Lev0 == HIGH){
LStat = 1;
delay(500);
Lev1 = digitalRead(LVS);
if(Lev1 == HIGH){
LStat++;
}
delay(500);
Lev2 = digitalRead(LVS);
if(Lev2 == HIGH){
LStat++;
}
if(LStat == 3 || Lev2 == HIGH){
Level = 1;
}
}else{
digitalWrite(Valve, HIGH); //Air valve OPEN
digitalWrite(RUN, HIGH); //RUN LED light
LStat = 0; //LStat reset
delay(1000);
}

varP++;

//Debug only
//Serial.println(varP);
//Serial.print("Level Sensor check = ");
//Serial.println(Level);

}


//Stop pumping-----------------------

//Debug only
//Serial.println("Stop pumping");
//Serial.print("Level Sensor = ");
//Serial.println(Level);

digitalWrite(Valve, LOW); //Pumping stop, reached on max time
digitalWrite(RUN, LOW); //RUN LED dark
if(Level == 0 && Reset == LOW){
while(Reset == LOW){ //Error TimeUp, waiting for Manual RESET
digitalWrite(ERR1, HIGH); //LED1 ON-OFF
digitalWrite(ERR2, LOW); //LED2 ON-OFF
delay(500); //Waiting for RESET SWITCH
digitalWrite(ERR1, LOW);
digitalWrite(ERR2, HIGH);
delay(500);

//Debug only
//Serial.println("TimeUP");
}
digitalWrite(ERR1, LOW); //ERR LED1 Cancel
digitalWrite(ERR2, LOW); //ERR LED2 Cancel

//Debug only
//Serial.println("RESET");
}

} //If reset SW is ON, return to beginning
}


void RESET() {
ctR = millis(); //Anti-chattering
if((ctR - ptR) > bounceR && ptR != 0){
Reset = HIGH; //When push RSS
digitalWrite(ERR1, HIGH);
digitalWrite(ERR2, HIGH);
digitalWrite(RUN, HIGH);
delay(1000);
digitalWrite(ERR1, LOW);
digitalWrite(ERR2, LOW);
digitalWrite(RUN, LOW);
}
ptR = ctR;
}

液面維持システム その4 ArduinoアップデートXXX

2017-02-18 23:38:53 | ABCのAはArduinoのA
しばらく更新していなかったので
Arduinoのソフトをアップデートしたら
書き込めなくなってしまった。

中華Arduinoを使っているから
USBドライバーが合わなくなったのかな、と
そっちも入れ直す。
掲示板を見たら
もう一度インストールすると良さそうな事がかいてあったので
やってみるが、ダメ。

よく読むと前のバージョンに戻すと良いように書いている人もいた。
仕方なく、1.8.1最新版から前の1.6.8に戻す。
インストールファイルを残しておいて良かった....

そしたら問題解決。
意外と最新版が一番と言うのでもないのだなと認識。

さて、今日はハードウェアの作成。

エラーのLEDは大きな物で5V駆動か素のままのが無いらしいので
ケース入りを2個使って交互に点滅させる事にした。
目立たせるため。
写真では直接付いているが
リード線でパネルまで持って行く。

リセットスイッチはこれでは無いが
似たようなパネル設置用を使う。

が、ちょっとちゃんと動かなくなった。
どこか間違えたらしい。
今日はこれでお休み。

液面維持システム その3

2017-02-12 12:48:15 | ABCのAはArduinoのA
以前にも割込を使ってプログラミングした事があったけれど、
あの時は見よう見まねで概念としてあやふやな部分があった。
今回やってみてやっと意味が掴めた感じがしている。

割込はattachInterrupt...で定義しておくと
そのピンの先で起きた事、
例えば電圧がHIGHになる、LOWになる、単に変化すると言うような事だけれど、
これを検出、
その後すぐに定義の中に書いたサブルーチンに飛んでそれをやる。
その時途中でも今やっている事を中断。
サブルーチンが終わると元のところに戻ってくる。

セオリーとしてはサブルーチンの中で変数の中の値を変える。
(一般的なセオリーを無視してサブの中でもっといろいろやれないでもないが、
検索の結果、そんな事する人はいないらしい。)
その変えた変数を元のメインのプログラムで使うようにしておくと
メインのプログラムの処理がその変数によって変わる、と言うわけらしい。

逆にもしメインのプログラムの中でサブルーチンの変数を使わないようにしていると
いくら割込で変数の中身を変更しても何も起きない。
...と言う事のようだ。

リファレンスの中では構文は説明してくれているけれども、
こうした一般的な使い方は検索してたくさんのプログラムを見ないと
わからない。
これが初心者の壁になっているけれど、
インターネットでみなさんが例文を公開してくれているのでありがたい。



液面維持システムのスケッチは下記の通り。
机上テストでは何となく出来そうな感じ。

動作の要点
1.最初は給液までの時間待ち。(ここでは10分)
2.ポンプON。
3.ポンプOFFは(1)液面上昇、(2)リセットまたは(3)設定時間が来たの
 どれかでOFFになる。
4.ポンプOFFは設定時間でOFFになってしまったらこれはエラーとする。
 液面センサーが壊れているかタンクが漏れているなどが考えられるため。
5.エラーが発生すると赤LEDを点滅させる。
 エラーはリセットスイッチを手動でONにしないとそのままとなる。
6.エラーを人がリセットするとまた1番に戻る。
7.液面上昇かリセットでポンプOFFの場合は単に1の時間待ちに戻る。

リセットスイッチ長押しモードも作って
待ち時間なしでポンプONと言うのもやろうかと思ったが、
その時は人が近くに必ずいるわけだから
バケツに液を汲んで入れれば良いので止めた。
100%完全自動を目指しているわけではないし。


以下、スケッチ参照ください。
また間違いあれば指摘していただけると嬉しいです。(初心者なので)


//出力ピンの番号
int RUN = 5; //ポンプがONの時に点灯するLED出力のピン
int ERR = 6; //エラー(タイムアウト)で点灯するLEDのピン
int Valve = 7; //エア・ポンプのエアを開閉する電磁弁用のリレーのピン

//入力ピンの番号
int LVS = 2; //液面センサー(当初、割込で使うつもりで2番にした)
int RSS = 3; //リセットスイッチ

//割込のための変数を設定
volatile int Reset = LOW; //リセット・スイッチのサブルーチンで使う

//液レベルのための変数
int Level = LOW; //Valve initial status

//各時間設定の変数 - 変更が必要ならここを変更する
int TimeW = 10; //給液までの待ち時間を分単位で設定
int TimeP = 60; //ポンプをONにしている最大時間を秒単位で (最長になるとたぶん液面センサのエラー)


//リセットスイッチのチャタリンング防止のための変数設定
volatile int bounceR = 100;
volatile int ctR;
volatile int ptR = 0;




void setup() {

Serial.begin(9600); //デバッグのためにシリアル通信

//OUTPUT PIN
pinMode(RUN, OUTPUT); //最初にポンプRUNのLEDはOFFにしておく
pinMode(ERR, OUTPUT); //エラーのLEDも最初はOFF
pinMode(Valve, OUTPUT); //ポンプのためのエアも最初はOFF

//INPUT PIN
pinMode(LVS, INPUT_PULLUP); 液面センサーは内蔵プルアップ使用
pinMode(RSS, INPUT_PULLUP); リセットスイッチは内臓プルアップ使用

//INTERRUPT
attachInterrupt(digitalPinToInterrupt(RSS), RESET, RISING); リセットスイッチ割込

//Level sensor Normal-ON type 注釈:液面センサーは通常ONで液面上昇でOFFとなる
}

void loop() {

//Debug only
//Serial.println("Start");
//Serial.print("Reset=");
//Serial.println(Reset);

//ポンプONまでの時間カウント開始------------------

Reset = LOW; //念のためリセット信号はLOWにしておく
while(Reset == LOW) { //リセットされていない間だけカウントする

//Debug only
//Serial.println("Waiting start");

digitalWrite(Valve, LOW); //Valve close
digitalWrite(RUN, LOW); //RUN LED reset
digitalWrite(ERR, LOW); //ERR LED reset

//この下のカウンターは2重になっていて中は1分カウンター、外は指定時間までの分カウンター
//どちらもリセットがかかったら抜け出すようにしている
int varW = 0;
while(varW < TimeW && Reset == LOW){ //time timer in min. If Reset pushed, stop waiting
int varW0 = 0;
while(varW0 <= 60 && Reset == LOW){ //1min timer. If Reset pushed, stop waiting
delay(1000);
varW0++;
}
varW++;

//Debug only
//Serial.print(varW);
//Serial.println("min");
}

//ポンプ給液スタート------------------

//Debug only
//Serial.println("Pumping start");
//Serial.print("Level sensor =" );
//Serial.println(Level);

int varP = 0;
Level = digitalRead(LVS); //最初に液面センサーを確認しておく
while(varP < TimeP && Level == LOW && Reset == LOW) { //時間まで、液面低い、リセットしてないが条件
digitalWrite(Valve, HIGH); //ダイヤフラムポンプの電磁弁ON 給液開始
digitalWrite(RUN, HIGH); //LEDでポンプONを表示
delay(1000); //1秒サイクルで各条件を確認する
Level = digitalRead(LVS); //液面確認 (リセットは割込なので記述しなくても良い)
varP++;

//Debug only
//Serial.println(varP);
//Serial.print("Level Sensor check = ");
//Serial.println(Level);

}


//ポンプ給液を停止する-----------------------

//Debug only
//Serial.println("Stop pumping");
//Serial.print("Level Sensor = ");
//Serial.println(Level);

digitalWrite(Valve, LOW); //時間最大か液面上昇でポンプは止まる
digitalWrite(RUN, LOW); //給液LEDを消す
if(Level == LOW && Reset == LOW){ //止まった時に液面が低くリセットもしていないとエラー
while(Reset == LOW){ //人がリセットを押すのをずっと待っている
digitalWrite(ERR, HIGH); //エラーのLEDを点滅する (0.5秒毎)
delay(500);
digitalWrite(ERR, LOW);
delay(500);

//Debug only
//Serial.println("TimeUP");
}
digitalWrite(ERR, LOW); //エラーのLEDを消灯

//Debug only
//Serial.println("RESET");
}

} //リセットを押したら最初に戻る
}

//リセットのサブルーチン
void RESET() {
ctR = millis(); //チャタリング防止のため
if((ctR - ptR) > bounceR && ptR != 0){
Reset = HIGH; //リセット信号をHIGHにする
}
ptR = ctR;
}

液面維持システム その2

2017-02-11 23:59:59 | ABCのAはArduinoのA
やっと時間がとれるようになったので
液面維持システムのテストを開始。

パーツは全部揃った。

液面レベルセンサーは例によってlelong.myの通販で購入。
あそこの通販、楽天やAlibaba等と似たようなもので
素人含め各店舗がサイトに店を出しているのだけれども、
けっこういい加減だ。

販売者の情報が何も書いてないのが多い。
連絡先はsmsやメールアドレスがあったりするが、
いったいどこから送られて来るのか
売っているのが個人か法人かもわからない場合がある。
一応ショッピングプロテクションがあるにしても
警戒はした方が良いだろう。

(マレーシアのネット通販、安心感でも中国に劣る。
それに小さい物での送料がRM7、と言う事は250円位かかるので
待てるなら中国から国際便で送ってもらう方が安かったりする。
送料に関しては日本でも同じ逆転が起こるだろうけれど...)



液面センサーは溶剤入りの液体を扱うのでステンレス製。
マイクロスイッチが入っていて、
液面が低い時に開、液面が高い時に閉になる物だった。
Arduinoの内臓プルアップを使うのでこの論理は逆転する。

リレー先日プドゥに行った時に店で買った。
通販もできたのだけれど、店で。
ノーマルONもノーマルOFFもどちらも選べるが、
故障時に停止して欲しいのでノーマルOFFで使う。


ポンプは写真に無いが工場にあった中古品。
ポンプはエア駆動のダイヤフラム式。

それを駆動する電磁弁も中古だがSMC製。
これは200Vレベルの電源が必要。
これを駆動するのがさっき言ったリレーとなる。

画面には書いていないけれど、
これにリセット用の小型スイッチも追加。
どこにもある押した状態を維持しない、
押した瞬間だけONになる物。
このスイッチはちゃんと割込で使う。
それとソフトでのチャタリング防止も行う。


プログラムは1月31日に書いたものを全面変更。
液面センサーを割込で使うのを止めた。
ポンプがONしている時に監視するだけなので
普通にON-OFFチェックで十分だと思ったから。

もう1つの理由はチャタリング防止をソフトで入れると
上手く動かなかった事。
そんな事で苦労しなくてもあるサイクル毎に見れば
チャタリングなどそれほど問題にならないだろう。

プログラム(スケッチ)はまた今度掲載予定。

液面維持システム その1

2017-01-31 13:20:21 | ABCのAはArduinoのA
チーチ3号計画が頓挫して随分と時間が経ってしまった。
キャサリンさんにも捨てろと言われてしまっている。

が、ここに来てようやく時間ができたので別のプロジェクトを開始。
内容はそんなに難しくは無さそうなもので、
液面維持のシステム。
タンクの液体が減ったら継ぎ足すと言うもの。

継ぎ足すきっかけは時間がある程度経過した時。
継ぎ足しを止めるのは液面センサー。
これはマイクロスイッチの入っているフロートセンサー。
一般的な物だ。

センサーが壊れてOFF故障すると危険なので
継ぎ足しも最長時間を決めておいて最長まで行ってしまったら
エラーを出す。

継ぎ足しポンプが動かない時に
出力が出ていて動かない、つまりポンプが壊れているのか
それとも信号が出ていないのか判別するための
RUN信号LEDも付ける。

リセットスイッチも付ける。


リセットスイッチと液面センサーは割込みとして使う。

買わなきゃいけないのはポンプにエアを送り込む
電磁弁(日本では1000円程度)。
リレーユニット。
リレーそのものではなくてユニットになってる物。
使うのが簡単だから。

ダイヤフラムポンプはある物を使う。
キャパシティオーバーだけれど買うと高いから。



マレーシアの場合、外国人労働者が安い賃金でいるから
この作業は人手でやっても良いのだけれど、
想定ではだいたい10分に1回やる必要があってなかなか大変。

そうなると夜勤などでこの10分間隔が
本当に維持できるかどうかがわからなくなって来る。
例えば20から30分になった時があったとしたら
それが品質にどう影響していたかがわからなくなる。
わかるには破壊検査が必要になる。

なので半自動化しようと思っている。
簡単そうだし。






以下、スケッチ追加。
(書いただけで未検証。間違い多数の可能性大。)




火事検出器 その2

2016-10-09 19:55:09 | ABCのAはArduinoのA
7月から放り出してしまっていた火事検出器、
やっと日の目を見ることになった。

放り出していた理由は別の事を工場の現場管理に任せていて
それが全然出来て来ない。
だからこれをやらせるわけにいかなかったと言う事。
そうしている間に新しい機械が来たのでそちらに先に取り付ける事に。

なので機械に合わせてセンサーも2個から4個に増やした。
それ以外は何も増やしていない。
スケッチをちょっといじっただけ。


ここから後半。


さて、これを作るのに一番苦労したのは何か?
それはハンダ。
細かいからじゃなくて、ピンも銅線もハンダが付きにくい。
安い中国製だから材質が悪いのか、
表面が酸化しているのか?
それともたぶんこれも中国製と思われる
ヤニ入りハンダが悪いのか?

まさかそんな事でこんなに苦労させられるとは…

それで基板にピンをたてたかったのだけれど、
直接銅線どうしを基板上のハンダブリッジで接続したりしている。
この問題、チーチ3号でもそうだったので
近い将来何とか考えたい。