2020年9月29日火曜日

グルーガンを新調してみた

これまで使っていた百均で買ったグルーガン、この4月にパイロットランプを付けたばかり ですが調子が悪くなりました。引き金を引いてもグルースティックがスリップしてしまい押し出せません。スティックがツルツルしてきた気もしますが、本体を買い換えることにしました。

50Wで立ち上がりが早いというモノです。多くの種類がありましたが、先端が細長くて狭いところに入り易そうなものを選びました。アマゾンで1,700円位です。スティックが30本付いてきました。

50Wと書かれていますが、電圧が100V〜240Vです。電圧変換などはやってないはずなので、何Vの時に50Wなのでしょうか? 普通に考えたら最大電圧240Vの時に50Wのように思えます。100Vだと20W位? 今度、電流を測ってみましょう。

百均のグルーガンと並べてみました。ふた回り位大きいですが重くはなく持ち易いです。電源スイッチが付いていて片手でオンオフできます。スティックの直径はどちらも7mmですが、長さが随分長い。

通電して1分半位で溶け始めました。グルーは百均グルーガンより高温になっているようで、粘着力も強めでよい感じ。スイッチもスリップせずに快調に押し出せます。当たり前か!

2020年9月26日土曜日

アンモボックスのレストア(その2)

またまた週末に雨ですね。みんな外出しずらいので新型コロナの感染防止にはよいのかも知れませんが、ちょっとウンザリ。屋外の作業ができないので先週に続いてアンモボックスのレストアです。

ホルツの塗装はがし液、ペイントリムーバを買ってみました。使うのは初めてです。ネットの評判が良かったので試してみます。さて軍用塗装が剥がれるでしょうか?


ドロッとした液体です。皮膚につくと痛いというので耐薬品用のゴム手袋も一緒に購入しました。匂いもキツイです。記憶の彼方にある匂いでしたが思い出せません。そのうち思い出すかも。匂いの記憶は結構強い記憶で、昔のことでもその時の情景が思い出されますよね。私だけ?

ハケで厚めに塗って30秒位待ちます。というか端から塗っていけば一面塗り終わる頃にはそのくらい経っている。


スクレーパで擦ると面白いように剥がれていきます。すごい。この削ったカスが素足に少しだけ飛んだのですが皮膚が痛くなりました。なんだか痛いなぁと思って足下を見たら付いていた。直径1mmにも満たない小さなモノでしたが強烈です。

凹凸があるとスクレーパでは剥がせないので、ワイヤブラシを使って剥がします。ワイヤブラシを使うとカスが飛ぶ。箱の隅はこんなドリルの先端に付けるワイヤブラシを使いました。

本体が終わり、蓋に取りかかりますます。ダンボールに飛び散っているのが削りカスです。触ると危険。形状が込み入っている所は中々一度では剥がせないので、二度三度と塗布して剥がしました。

一通り剥がし終わって水洗いした後です。薬品が付いたままだと危ないのでタワシでよく擦って洗い流しました。すすいだ後は錆びないようにドライヤでよく乾かして今日の作業はお終い。

洗い流してキレイになると未だ塗装が残っているところに気付いたので、明日もう一度剥がします。そのあとワイヤブラシや紙ヤスリで錆を落とせば下地は完了です。でこぼこも直せる所は補修。

さらに脱脂して、下塗りの錆止めを塗るつもりです。明日はそこまでかな。

2020年9月20日日曜日

アンモボックスのレストア開始

折角の4連休ですが天気が悪く外周りの作業ができません。夏休みから1ヶ月以上も経ったのにまだ夏のToDoリストが残ったままです。

そんな訳で以前、弾薬箱を使った工具箱 で書いたアンモボックスのレストアを始めてみました。書いたのはもう2年近く前のことでした。中々重い腰が上がらなかった訳は、蓋の周囲に充填してあったパッキン樹脂が変性してカチカチの石炭のようになってしまっていたからです。これが硬くて簡単には取れないので諦めてました。これを取り除かないと蓋が閉まらないのです。

ようやく決心して、貫通ドライバをタガネのように使いハンマで叩き、砕きながら取り除くことに。うるさいし、少しずつしか取れないし、イヤになりながら中腰での作業を1時間半ほどかけてようや決着しました。

写真は途中まで(写真右下1/3位)取り除けた様子。

下記はヒンジ部分の元パッキンを取り除いた様子。

完了です。黒いのが取り除けた元パッキンです。ホントに石炭のようです。元々が石油由来の材料だったのか?

蓋が閉まるようになり、ロックもかかります。取り除けたパッキンの代わりにはシリコンシール剤を充填しようかと考えています。弾性もあるので充填しても蓋が閉まるのでないかと期待してます。


箱の凹凸やゆがみをペンチとハンマで直し、側面を紙ヤスリで擦ったら、オリーブドラブというミリタリ色が復活しました。箱が所々凹凸ができているので、凸部分は削れて白く金属肌が出ています。

この塗装を剥がすのは大変そうです。錆びているところだけ磨いて、そのまま上塗り塗装してしまうか? 或いはペイントリムーバで塗装を剥がしてみるか? 軍用のしっかりした塗装が剥がせるかわからないですが、試してみたい気もあります。手元にないので買わないといけない。

また、箱内側の底隅が結構錆びててヤスリがけが大変そうだし、レストアはまだまだ始まったばかりです。

2020年9月19日土曜日

大きなLEDランプの動作確認と修理

壊れたLEDランプを手に入れました。街灯に使われている大きなモノです。台風で落下して壊れたらしく外装は粉々に! 中身は大丈夫のようだったので廃棄寸前に回収しました。


取り付け側はこんな感じです。一部ひび割れができています。

分解してみると電源回路が入っていて、S28-36W-02となっています。36Wのようです。上の写真でもLED-36と刻印されてます。普通のLED電球は60型で7W位なので、60型の5倍の明るさでしょうか?

しかしこの電源モジュール、ヒートシンクまで完全に防水シールされていて放熱は大丈夫か? 写真左上のヒートシンクはシールから免れています。

念のためにヒューズ入りコードでAC 100Vを繋いでみたら無事に点灯しました。写真は露出が自動的に絞られてしまい暗く見えますが、非常に明るいです。これひとつで部屋全体が十分明るくなります。

点灯することが分かったので、割れたケースの補修をすることに。落下の衝撃で割れたのでしょう。

タミヤセメント(プラモデルなどに使う接着剤)を隙間に流して、クリップで挟んで密着。無事にくっ付きました。

使用するにはカバーや取り付け方法を考えないと。使うところあるかな?

2020年9月18日金曜日

Gmailのpop受信トラブルと解決法?

gmailをpopで受信しようとするとかなりの確率で下記のエラーがでて繋がらない。繋がるのは20%位の確率で、一度繋がるとしばらくは大丈夫。でも繋がらない時は全然ダメ。メーラの設定を色々と変えても変わらず。


半年ぐらいほっておいたのですが、あまりに不便なので色々ググってみても、どれも設定のことばかりで解決に至らず。受信できたりできなかったりする現象の事例が見つからない。そんな中、アンチウィルスソフトが悪さしているにでは?というQ&A記事を見つけた。アンチウィルスが原因ならいつも繋がらないはずでは?  試しに半信半疑で止めてみました。

アンチウィルスソフトは無料のアバストを使っています。そのメールシールドという機能を止めてみました。止める時に危ないよ、と注意喚起されますが、ひとまず10分間だけ止めてみました。

すると、エラーが起きずにgmailが受信できました。たまたま大丈夫な20%に当たった可能性もあるので、時間をおいて何度か試してみたら、アンチウィルスを止めるとエラーなく受信できるようでした。

なんでアンチウィルスが動いていても大丈夫な時があるのかわかりませんが、何か理由があるのでしょうね。

でも受信のためにアンチウィルス止めたら、ウィルス添付メールの検疫ができないよね。どうしたもんだ。

以上、備忘録と同じような現象が起きている人との情報共有のための記録です。

2020年9月13日日曜日

オーブントースタの温度制御(続き2)

温度制御をPID制御してみようと調べたら、Arduinoのライブラリがありました。早速組み込んでみましたが思うように制御できません。元々のプログラムの制御方法と上手く合わないのと、PIDのパラメタを全くチューニングしてないためかと思います。

とりあえず、温度設定時の温度上昇下降の斜め線をやめて、単純オンオフ制御で様子を見てみました。オーバシュートは少し早めに(低い温度で)オフにすれば改善できそう。それより問題だったのは長時間過熱すると200℃でも過熱防止サーモスタットが効いてしまうことでした。200℃になって1分位で強制オフになって温度が下がっています。14分位で復帰しましたが、200℃になる前に時間切れです。

という事で、PID制御の調整も面倒だし、頑張ってもサーモスタット次第のところもあるので、このくらいでおしまいにしようかと思います。サーモスタットを外す手もありますが、危険なのでやめておきます。

あとはユニバーサル基板に載せ替えてケースに入れて常用にするかですが、温度制御の自由度が思った程無いので、どうするか悩みどころ。

2020年9月12日土曜日

オーブントースタの温度制御(続き)

久しぶりに涼しい休日になりましたが雨なので屋外作業ができません。夏休みのToDoリストの屋外作業がまだ終わらないのです。週末、2日晴れてくれればよいのですが、ままなりません。

温度コントローラの 熱電対の温度追従が遅くて苦戦 したので新たに注文していた熱電対が届きました。2つのショップに別々に注文して、無事に両方届きました。ひとつは台湾から、もうひとつは大陸からで4日程の時間差でした。値段が送料込みで53円と59円と破格です。ハガキの郵便料金より安い。
端子が平らだったのでMAX6675モジュールにプラグの端子を無理矢理取り付けます。最終的にはプラグのプラスチックを分解してきちんとネジ止めします。

温度コントローラ全景です。モバイルバッテリで動作させてます。右端の大きなヒートシンクに載っているのが40AのSSRで、オーブントースタへの給電をオンオフします。

熱電対の先端はトースタ上下にあるヒータの中間くらいにしました。トースタは空の状態で無負荷です。空焚きはよろしくないかも。

温度設定を250℃にして試していますが、オーブントースタ内蔵の過熱防止サーモスタットが動作してしまい、そこまで上がりません。最初は約240℃でオフになり、再びオンになるのは約150℃です。その間約2分、温度が再び上昇して次は約225℃でオフになりました。サーモスタットのある場所が温まっていたからだと思います。その後は、10分の設定時間を過ぎてしまったので温度はなだらかに下がっていきます。
サーモスタットが効かないように最大220℃位までの範囲で制御した方がよさそうです。一度サーモスタットが動作すると150℃に下がるまで復帰しないので、全く温度制御できなくなります。

次に150℃と200℃の設定で動かしてみました。制御は単純オンオフで、設定温度未満ならオンで、設定温度に達したらオフにしています。
150℃を越えたらオフになっていますが、少しオーバシュートが出ています。さらに200℃に向かう時間が早いように見えていますが、最初の150℃に達するまでの斜めのラインも3分に含んでいるためです。この辺り要調整です。200℃を越えたらオフになりましたが若干オーバシュートです。

内部に食材を入れたらもう少し温度上昇が緩やかになるかもしれません。今は設定温度への上昇/下降の傾斜線を入れていますが、実態はこれに合うか微妙なのと、設定時間に温度上昇分を含むか否かを考えるのが面倒になってきました。

設定は斜め線を無くして矩形でもよいかと思い始めています。とりあえず、オーブントースタの特性が分かったので、どんな仕様にするか考えます。余り凝っても思うようには動かなそうなのでほどほどに。

2020年9月6日日曜日

オンボード電源を試してみる

これまで5Vの電源が必要な場合、20mA程度迄ならコンデンサを使ったトランスレス電源を使い、それ以上はACアダプタやUSB給電を使ってきました。外付けのACアダプタは必要な時に見つからなくなることもあったので、ケース内にACアダプタを内蔵したこともありました。ただ、そうするとスペースをとってしまいます。

最近、ArduinoやESP32を使うことも増えてきたので、オンボード用の電源を購入してみました。ACアダプタより省スペースです。5Vと3.3Vを5個ずつ、US$1.45/個でしたが別途送料がかかって合計US$21.62でした。1個あたり230円程です。ACアダプタより安い。その分、ACプラグなどは必要になりますが。


型番はHLK-PM01、入力は100~240V、出力は5V 0.6Aで3Wです。

裏側です。100V側の2本のピンが近くて(ピン中心で5mm位)ちょっと心配ですが注意して工作すれば大丈夫でしょう。5V側はピン中心間隔が15.2mm位でした。それぞれはユニバーサル基板に刺さるピン間隔ですが、100Vと5V側のピン中心間隔が29.2mmなので残念ながらユニバーサル基板に刺さりません。ちょっと穴を大きくすれば刺さりそうですが。

評価のためにAC100Vを繋いでみます。テスト用に100Vプラグをミノムシクリップにしてある治具(ヒューズ入り)があるのでそれで挟んでみますが、ピン間が近いのでビニールテープで絶縁しました。

負荷電流を0.1A~1Aまで変化させて電圧の変化をみました。電流、電圧共に電子負荷のディスプレイに表示されているものです。無負荷で5.04V、0.2Aで5.03~5.04Vを行ったり来たり、0.5Aで5.01V、定格オーバの1Aで4.99Vと、まずまず安定しています。ちなみに1A以上で自動的にオフになったので安全回路が入っているようです。

オシロで波形を見てみましたが若干ノイズが乗っています。電子負荷だと負荷のノイズが乗るかと思い、抵抗負荷を使い0.2A位取り出したときの様子です。ひと目盛りが1Vなので0.1V位でしょうか。まあPICやArduinoなどの用途なら問題ないでしょう。

発熱状況も見てみました。室温29℃で0.5A流し続けたときのモジュールの温度です。体温とほぼ同じでほんのり温かくなる程度でした。ただし、定格外の1Aを取り出したら44℃まで上がりました。

3.3Vの電源HLK-PM03、定格1A、3Wも同様に評価してみました。電流値を1Aまで変化させたときの電圧は安定していました。電源ノイズも5Vと同様に乗ってます。負荷が大きい時のリミッタは1.7A位で動作しました。

ただ問題があり、0.2A位から「チー」という高い音が聞こえます。5Vモジュールは音は聞こえませんでした。個体差かと思い他の個体も確認しましたが同様です。ちょっと残念ですね。小さな音なのでケースに収めれば聞こえないかもしれません。

耐久性などはわかりませんが、一応使えそうなので今後の工作で使っていこうかと思います。価格がトランスレス電源の部品代と大差なく、大きさも似たような感じですが3Wも取りさせるのがよいです。

少々高いですが、アマゾンでも購入できます。

2020年9月5日土曜日

1,350円の電子負荷を買ってみた

電源周りの簡単な評価用にAliexpressでUS$13弱(1,350円位、送料無料)の電子負荷を買ってみました。これまでセメント抵抗などを使っていましたが連続的でないし、狙った抵抗がないなど不便でした。自作しようかと思いましたが安く買える事が分かったので購入です。以下は昔、抵抗負荷で評価している動画です。

今回買ったものはUSB端子がついていて主なターゲットはモバイルバッテリやACアダプタの評価用ですね。 測定範囲は4〜25V、0.1〜4.5A です。冷却用のヒートシンクとファンが付いていて、ファンは55℃を越えたら自動的に回り始めました。ディスプレイに温度も表示されています。まだ43℃なので回っていません。

積算時間や電力量なども表示でき、表示モードを切り替えるタクトスイッチの長押しでリセットできました。

表示モードを切り替えた様子です。

左側はメインの電流調整用ボリウムで、右側が微調整用です。真ん中は圧電ブザーで、電流が許容範囲を超えたりすると警告音が出ます。

仕様では4.5A迄となっていますが、試したら5Aを越えたところで警告が出ました。

ディスプレイの反対側の基板裏には各種USB端子が付いていて、様々なアダプタを繋げられます。左端のターミナル(赤黒のコードを接続してみました)からも給電できるので、USB電源以外の評価に使えます。

電流と電圧の精度は、手元のテスタと比べたら少ない電流のときに若干異なりましたが、1Aくらい流すとほとんど同じ感じでした。電圧は若干高めにでる感じ、と言っても5Vで1%も違いませんでした。安いテスタの精度も不明なのでなんとも言えませんね。ちなみに定格外の3.3Vで試したら一応動きましたが、3.7V位が表示されて誤差が大きいようです。

付いてきた取説はハガキより一回り小さいこれ1枚です。文字がかすれたりしていて読みにくいが付いてきただけましか。

ボリュームの回転と電流の変化がイマイチ連続的でないときもありますが、値段の割に多機能でよくできている感じです。この値段ではとてもじゃないが自作できない。

2020年9月3日木曜日

インターバルタイマの製作

久しぶりに インターバル・タイマ(間欠タイマ) の製作を行いました。AC100Vのオンオフを秒単位で、最大99時間59分59秒までのインターバルで設定できるものです。時々製作の依頼があります。皆さん「インターバルタイマ」などのキーワードで検索されて、このページ にたどり着くようです。


依頼のインターバルはないときは全然ないのですが、あると続くケースが多いです。今回も1ヶ月の間に2件ありました。製作は意外と手間で、作業時間を時給換算すると東京都の最低賃金程度なのですが、基板屋さんに委託して作った基板の在庫があるうちは続けようかと思っています。



余り部品の在庫を持ちたくなく、依頼があると部品を購入するので、その送料などもかかってしまい利幅は少ないです。最近送料も高くなっているし。ただ、ついでに自分の工作に使う部品も一緒に買えるのでまあよいかと。

沢山需要があるなら、製作を中国などに外注してもよいのですが中々難しいですね。家内工業で細々と続けて行きましょう。

2020年9月1日火曜日

夏休みの工作、小型フォトフレーム

夏休みの仕上げとして、XIAOと小型カラー液晶で作ったフォトフレームの動画アップしました。



--
21.04.21 追記
あまりキレイではありませんがスケッチです。無保証です。著作権は留保しますが、改変などご自由にどうぞ。
回路(結線)はスケッチと XIAOと1.8インチ小型液晶で小型フォトフレーム をご参照ください。タッチスイッチのピンは、スケッチ内に記載。

//                                                    2020.08.19 naka
// Small Digital Photo frame (Signage)
//
#include <Adafruit_GFX.h>         // Core graphics library
#include <Adafruit_ST7735.h>      // Hardware-specific library
#include <SdFat.h>                // SD card & FAT filesystem library
#include <Adafruit_ImageReader.h> // Image-reading functions
#include <FlashAsEEPROM.h>        // XIAOにはEEPROMがないのでflashをEEPROMのように使うライブラリ
#include <FlashStorage.h>

#define SD_CS    7 // SD card chip select
#define TFT_CS   4 // TFT select pin
#define TFT_DC   6 // TFT data/command pin
#define TFT_RST  5 // Or set to -1 and connect TFT RST to Arduino reset pin

#define TOUCHSW_1 2
#define TOUCHSW_2 3

#define FILENAME_SIZE 32
#define B_SIZE 32

SdFat                SD;         // SD card filesystem
Adafruit_ImageReader reader(SD); // Image-reader object, pass in SD filesys
Adafruit_ST7735      tft    = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
File root;
int  play;
int  interval;
#define MAX_FILE 50
char file_tbl[MAX_FILE][FILENAME_SIZE];
int file_num;

void setup(void) {
  // i/oピン設定
  pinMode(TOUCHSW_1,INPUT);
  pinMode(TOUCHSW_2,INPUT);
  
  tft.initR(INITR_BLACKTAB); // Initialize screen
  tft.fillScreen(ST77XX_WHITE);
  tft.setRotation(3);
  
  if(!SD.begin(SD_CS, SD_SCK_MHZ(10))) {
    message("SD card error");
    while(1);
  }

  read_flash(); // 設定値 (play,intervalをflashから読み出す) 

  ImageReturnCode stat = reader.drawBMP("amazon.bmp", tft, 0, 0);
  delay(5000);
  
  // ファイル名一覧を取り出す
  int i_file;
  char filename[FILENAME_SIZE];
  root = SD.open("/");  // rootにあるファイルのみ表示対象
  file_num = 0;
  while(get_next_file_name(root,filename,FILENAME_SIZE)) {
    if (strcmp(filename,"amazon.bmp")!=0) {
      strcpy(file_tbl[file_num++],filename);
      if (file_num>=MAX_FILE) break;
    }
  }

//  for (int i=0;i<file_num;i++) {
//    Serial.print(file_tbl[i]);
//    Serial.print("\n");
//  }

  qsort(file_tbl,file_num,sizeof(file_tbl[0]),compchar);
//  Serial.print("Sorted\n");
//  for (int i=0;i<file_num;i++) {
//    Serial.print(file_tbl[i]);
//    Serial.print("\n");
//  }

  char buff[30];
  sprintf(buff,"bmp file number : %d",file_num);
  message(buff);
  delay(2000);
}

void loop() {
  char filename[FILENAME_SIZE];
  char buff[B_SIZE];
  static int i_file = 0;

  if (play==0) i_file = rand()%file_num;

  ImageReturnCode stat = reader.drawBMP(file_tbl[i_file], tft, 0, 0);
  if (stat) {  // 読めないbmpファイルフォーマット
    sprintf(buff,"Not support %s",filename);
    message(buff);
  }
  int next = check_touchsw(); // 3秒表示
  if (next==1) {
    i_file--;
    if (i_file<0) i_file = file_num - 1;
  }
  else {
    i_file++;
    if (i_file>=file_num) i_file = 0;
  }
}

int get_next_file_name(File dir,char *buff,int size) {
  File entry;
  while(1) {
    entry =  root.openNextFile();
    if (!entry) {               // おしまい
      return(0);
    }
    if (!entry.isDirectory()) { // ファイルなら拡張子を確認してbmpならbreak
      entry.getName(buff,size);
      String fileName = String(buff);
      String ext = fileName.substring(fileName.lastIndexOf('.'));
      if (ext==".bmp" || ext==".BMP") {   
        break;
      }
    }
    else {                     // dirならクローズして次のエントリ
      entry.close();
    }
  }

  entry.close();
  return (1);
}

void message(char* text) {
  tft.fillRect(0,tft.height()-71, 159,10, ST77XX_WHITE); // 消去
  tft.setCursor(3,tft.height()-70);
  tft.setTextColor(ST77XX_RED);
  tft.setTextWrap(true);
  tft.setTextSize(1);
  tft.print(text);
}

int check_touchsw() {
  static unsigned int int_time[6] = {0,1000,3000,10000,30000,60000};
  unsigned int time_s = millis();

  while(1) {
    // touch swが押されているか
    if (digitalRead(TOUCHSW_1)==1 || digitalRead(TOUCHSW_2)==1) { // 押されている
      delay(100); // 同時押し確認
      if (digitalRead(TOUCHSW_1)==1 && digitalRead(TOUCHSW_2)==1) { // 同時
        select_menu(); 
        return(0);   
      }
      else if (digitalRead(TOUCHSW_1)==1) {
        return(1);
      }
      else if (digitalRead(TOUCHSW_2)==1) {
        return(2);
      }
    }
    else {
      if (interval!=0) {
        if ( (millis() - time_s) > int_time[interval] ) { // interval時間が経過した
          return (0);
        }
      }
    }
  }
}

void select_menu() {
  unsigned int pretime = 0;
  menu();
  while(digitalRead(TOUCHSW_1)==1 || digitalRead(TOUCHSW_2)==1); // 離されるまで待つ

  disp_triangle_play(play,0);
  disp_triangle_interval(interval,0);
  while(1) {
    if ((millis()-pretime)>300) {
      disp_triangle_play(play,1);      // blink=toggle 
      pretime = millis();
    }
    if (digitalRead(TOUCHSW_2)==1) {
      play++;
      if (play>1) play = 0;    
      disp_triangle_play(play,1);
      while(digitalRead(TOUCHSW_2)==1); // 離されるまで待つ
    }
    if (digitalRead(TOUCHSW_1)==1) {
      while(digitalRead(TOUCHSW_1)==1); // 離されるまで待つ
      break;
    }
  }
  disp_triangle_play(play,0);

//  disp_triangle_interval(interval,0); // 1:blink
  while(1) {
    if ((millis()-pretime)>300) {
      disp_triangle_interval(interval,1);      // blink=toggle 
      pretime = millis();
    }
    if (digitalRead(TOUCHSW_2)==1) {
      interval++;
      if (interval>5) interval = 0;    
      disp_triangle_interval(interval,1);
      while(digitalRead(TOUCHSW_2)==1); // 離されるまで待つ
    }
    if (digitalRead(TOUCHSW_1)==1) {
      while(digitalRead(TOUCHSW_1)==1); // 離されるまで待つ
      break;
    }
  }
  disp_triangle_interval(interval,0);

  write_flash(); // 設定をflashに書き込む(書き込み回数制限10,000位)
}

int compchar(const void* left, const void* right) {
    char *left_char  = (char *)left;
    char *right_char = (char *)right;

    return strcmp( left_char, right_char );
}


void menu() {
  tft.fillScreen(ST77XX_WHITE);
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(1);
  tft.setCursor(20,tft.height()-120);
  tft.print("PLAY");
  tft.setCursor(30,tft.height()-110);
  tft.print("random");
  tft.setCursor(30,tft.height()-100);
  tft.print("sort");  
  tft.setCursor(20,tft.height()-80);
  tft.print("INTERVAL");
  tft.setCursor(30,tft.height()-70);
  tft.print("manual");
  tft.setCursor(30,tft.height()-60);
  tft.print(" 1 sec");
  tft.setCursor(30,tft.height()-50);
  tft.print(" 3 sec");
  tft.setCursor(30,tft.height()-40);
  tft.print("10 sec");
  tft.setCursor(30,tft.height()-30);
  tft.print("30 sec");
  tft.setCursor(30,tft.height()-20);
  tft.print("60 sec");
}

void disp_triangle_play(uint16_t play,int blink) {
  static uint16_t preplay = 0;
  static int toggle = 0;
  uint16_t x1,y1,x2,y2,x3,y3;
  toggle ^= blink;

  if (blink==0 || toggle==1) {
    x1 = 20,   y1 = tft.height() - (111 - preplay * 10);
    x2 = x1+4,  y2 = y1 + 4;
    x3 = x1,    y3 = y1 + 8;
    tft.fillTriangle(x1,y1,x2,y2,x3,y3,ST77XX_WHITE); // clear previous triangle
  }

  if (blink==0 || toggle==0) {
    x1 = 20,   y1 = y1 = tft.height() - (111 - play * 10);
    x2 = x1+4, y2 = y1 + 4;
    x3 = x1,   y3 = y1 + 8;
    tft.fillTriangle(x1,y1,x2,y2,x3,y3,ST77XX_RED);
  }
  preplay = play;
}

void disp_triangle_interval(uint16_t interval,int blink) {
  static uint16_t preint = 0;
  static int toggle = 0;
  uint16_t x1,y1,x2,y2,x3,y3;
  toggle ^= blink;

  if (blink==0 || toggle==1) {
    x1 = 20,   y1 = tft.height() - (71 - preint * 10);
    x2 = x1+4,  y2 = y1 + 4;
    x3 = x1,    y3 = y1 + 8;
    tft.fillTriangle(x1,y1,x2,y2,x3,y3,ST77XX_WHITE); // clear previous triangle
  }
  
  if (blink==0 || toggle==0) {
    x1 = 20,   y1 = y1 = tft.height() - (71 - interval * 10);;
    x2 = x1+4, y2 = y1 + 4;
    x3 = x1,   y3 = y1 + 8;
    tft.fillTriangle(x1,y1,x2,y2,x3,y3,ST77XX_RED);
  }
  preint = interval;
}

void read_flash() {  // FlashAsEEPROM を利用
  if (EEPROM.isValid()) {
    play     = (int)EEPROM.read(0);  // play
    interval = (int)EEPROM.read(1);  // interval
  }
  else { // 一度も書き込まれていないので初期値として以下を設定
    play     = 0; // random
    interval = 0; // manual
  }
} 

void write_flash() {  // FlashAsEEPROM を利用
    EEPROM.write(0,play);
    EEPROM.write(1,interval);
    EEPROM.commit();
}