多機能タイマ製作5

前回の多機能タイマ4で、Youtube にも動作例をアップロードしました。時間パラメタなどを設定する画面で画面を一旦クリアして一画面丸ごと再描画していましたが、シリアル I/F で VFD モジュールを動かしているためにあきらかに動作が遅いのです。

  012345678901234567890
 +---------------------+
0|                     |
1|  YY __  hh __       |
2|  MM __  mm __       |
3|  DD __  ss __       |
4|  DAY ___            |
5|  ENT=Write RTC      |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|
 +---------------------+

上の画面例で言うと、1 行目の YY の設定をしているときは 1 行目だけ再描画すれば良いので、画面表示するコードに何行目を再描画すれば良いかの判定を追加。これで、目障りな画面のチカチカは減りました。ソフトのほうは、コンパイル後のスケッチのサイズ:13,832バイト(最大容量32,256バイト)なのでまだまだ余裕ありますが、一旦フリーズして。今後は苦手なケース加工へ移行していきたいと思っています。基本的に夜間、屋外で使用するので透明プラケースは避けようかとは思いますが、どうなることやら。

電池1本で LED 点灯

なんのひねりもございません。昔からあるブロッキング発振回路でございます。昨日作ろうかと思い Twitter でつぶやくと「ジュールシーフ」ですねと言われて、他人の受け売りを教えてくださる Google さんを見たところ等価のものでした。でもいいネーミングだと思います。

これは他のサイトに詳細説明はたくさんございますので、こちらでは説明しません。「ジュールシーフ」や「ブロッキング発振 LED」などで記事がたくさんみつかります。使う部品もほとんどないのですぐ出来ます。気分転換ですね。失礼しました。

多機能タイマ製作4

タイマの基本部分は以下の画面でなんとかする。ということで仕様はほぼ決定。コード書いていきます。

●ランニング画面(screenID=0)

  012345678901234567890
 +---------------------+
0|Interval Timer       |
1|Del 99'99 Num 9999   |
2|Int 99'99 Exp 99'99" |
3|                     |
4|Ramen Timer          |
5|A 99'99"  B 99'99"   |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|
 +---------------------+

0~6行は、実行中のステータス表示に使用する。

  ESC: メニュー画面
  ENT:時分をしゃべる

  チャイム音のあとに、hh時mm分です
  <NUMK VAL=hh COUNTER=ji>/<NUMK VAL=mm COUNTER=funn>de_su.

ラーメンタイマーは、満了時刻30秒前に

タイマーA あと30秒です
ta'ima-/e'i a'to/<NUMK VAL=30 COUNTER=byo->de'_su. 

タイマーB あと30秒です
ta'ima-/bi'- a'to/<NUMK VAL=30 COUNTER=byo->de'_su.

と事前通知を行ない、時間満了でチャイム2回鳴らす。



●メニュー画面-選択画面(screenID=1)

  012345678901234567890
 +---------------------+
0|Set DATE & TIME      |
1|Interval Timer       |
2|Ramen Timer          |
3|                     |
4|                     |
5|                     |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|
 +---------------------+

  ESC: ランニング画面に戻る
  ENT: 選択されたメニューを表示
  カーソル上下: メニュー選択

●メニュー画面-Realtime Clock(screenID=2)

Set DATE & TIME選択時の画面

  012345678901234567890
 +---------------------+
0|                     |
1|  YY __  hh __       |
2|  MM __  mm __       |
3|  DD __  ss __       |
4|  DAY ___            |
5|  ENT=Write RTC      |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|
 +---------------------+

  ESC: ランニング画面に戻る
  ENT: RTC に最新時刻書き込む。ランニング画面に戻る
  カーソル上下: 値上下
  カーソル左右: 項目移動


●インターバルタイマ設定画面(screenID=3)

  012345678901234567890
 +---------------------+
0|Interval Timer       |
1|  Delay    99'99     |
2|  Interval 99'99     |
3|  Exposure 99'99     |
4|  Num Shot  9999     |
5|  ENT=Start ESC=Back |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|
 +---------------------+

  ESC: ランニング画面に戻る
  ENT: インターバルタイマ開始し、ランニング画面に戻る

●ラーメンタイマ設定画面(screenID=4)

  012345678901234567890
 +---------------------+
0|Ramen Timer          |
1|                     |
2|  Timer A  99'99     |
3|  Timer B  99'99     |
4|  Enable   A X B X   |
5|  ENT=Start ESC=Back |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|
 +---------------------+

  ESC: ランニング画面に戻る
  ENT: ラーメンタイマ開始し、ランニング画面に戻る


動作の様子は以下の youtube に上げた動画のとおりです。

  • インターバルタイマ機能
  • ラーメンタイマ機能
  • 時間をしゃべらせる

などです。

現状は、画面に出すのを最優先でコーディングしましたので、vfd の描画を一々消してから再描画などやってまして、画面がチカチカします。今後は、再描画の範囲を減らして操作しやすいようにしていきましょう。

多機能タイマ製作 その3くらい

本日も少しコーディング。超基本部分になる時刻の表示と設定です。といってもこの多機能タイマの機能のうちインターバルタイマーやラーメンタイマーにはこの時計を使用する予定はありません。現在は単に現在時刻表示(画面並びに音声)するためだけの用途で実装しています。

検討中ですが、下記画面イメージで検討

□ランニング画面(screenID=0)

  012345678901234567890
 +---------------------+
0|                     |
1|                     |
2|                     |
3|                     |
4|                     |
5|                     |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|  最下行は常に時計表示
 +---------------------+

  0~6行は、実行中機能のステータス表示に使用する。

タイマー全部動かしたら下のような感じかな。検討中
  012345678901234567890
 +---------------------+
0|Interval Timer       |
1|Del 99'99 Num 999  * |
2|Int 99'99 Exp 99'99" |
3|                     |
4|Ramen Timer          |
5|A 99'99"  B 99'99"   |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|  最下行は常に時計表示
 +---------------------+



□メニュー画面(screenID=1)

  012345678901234567890
 +---------------------+
0|Set DATE & TIME      |
1|Interval Timer       |
2|Ramen Timer          |
3|                     |
4|                     |
5|                     |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|
 +---------------------+

  ESC: ランニング画面に戻る
  ENT: 選択されたメニューを表示
  カーソル上下: メニュー選択

□メニュー画面-Realtime Clock時刻設定」(screenID=2)

Set DATE & TIME選択時の画面

  012345678901234567890
 +---------------------+
0|                     |
1|  YY __  hh __       |
2|  MM __  mm __       |
3|  DD __  ss __       |
4|  DAY ___            |
5|  ENT=Write RTC      |
6|                     |
7|YY/MM/DD hh:mm:ss XXX|
 +---------------------+

  ESC: メニュー画面に戻る
  ENT: RTC に最新時刻書き込む。ランニング画面に戻る
  カーソル上下: 値上下
  カーソル左右: 項目移動

そして、それに則ってコーディングして動作確認中。リアルタイムクロックそのものは特に問題無いでしょう。ということろ。


多機能タイマの基本部分ができたので、これからはコーディング中心に

時計表示の基本部分が出来たので今後はマイコンではやりたくないユーザーインタフェースの設計です。今は RTC の時間を一定時間毎に VFD に表示するというところが出来ています。RTC には BCD で時間や日付が格納されていて、最初は

return(bcd - (6 * (bcd >> 4)));

のような形で BCD を BIN に変換して変数に格納していましたが、表示のところでなぜかその変数から読み出しても空っぽ。コンパイラの最適化の影響だとは思われますが個人的には変数に volatile を書くと負けと思っているので、そのまま BCD 値のまま扱うことにしました。(どうせ RTC は時計だけなので軽いのです)。

ということで、目先は

  • ケース組み込みに向けて部品の採寸
  • ラーメンタイマの仕様検討(時間間際にしゃべってお知らせ)
  • デジタル一眼用インターバルタイマの仕様検討
  • RTC の時間再設定画面の検討
  • 上記3項目の画面遷移をどうするか検討

というところでしょうかね。真っ先にライブラリ化したいのは、ボタン押されて、時刻やタイマ値の増減とそれの表示を連動させるところなどです。

Arduino のソースも、メインと、AquesTalk pico のクラスと、DS1307 RTC のクラス、Noritake VFD モジュールのクラスと増えてきましたね。今のところコンパイルして 7kB 程度なのでまだいけます。

多機能タイマの構成を少しいじっています。

先日の動作確認で AquesTalk pico を 5V 動作させてもあまり気にならない声だったのでシールドの電源を 5V 統一します。これに伴ない以下の変更を実施

  • AquesTalk pico は 5V 動作に変更。
  • 3.3V の電源ライン廃止
  • I2C レベルシフタ撤去
  • CDS は夜間使用がほぼ固定されるので廃止
  • デジタル一眼用のリモートコード対応

という変更をかけまして基板上の部品も少し変わりました。TLP521 も載せてカメラのリモートコード用軍端も接続。半押しと全押し両方信号出さないとシャッター切れなかったため、都合3本です。

多機能タイマ製作

AquesTalkPico ATP3011F1, Noritake VFD モジュール、リアルタイムクロックで作りかけの多機能タイマもどきのビルディング中。これは写真撮影、天体観望などお外で使いたいと思っているものです。

基本的なモード

  • 現在時刻の表示
  • ボタン押したら時刻をしゃべる(まだボタンは未配線)

追加要素

  • ラーメンタイマ(時間間際にしゃべって知らせる)
  • デジタル一眼用インターバルタイマ(まだ未配線)

Arduino のスケッチで I2C 接続している RTC と AquesTalk Pico, シリアル接続の VFD モジュールの接続確認出来た状態でコンパイル後 5KB くらい。マイコンは32kB なので入って欲しいなぁと思いつつ。割り込み使う方法か、メインループでベタに時間見ながら処理するかが実は決まっていないというひどい状態。ここらへんはトライ アンド トライ でいきましょう。

AquesTalk pico ATP3011F1-PU I2C 3.3V接続の確認

AquesTalk pico の資料によりますと、クロックは内蔵RCオシレータの設定になっていて 3V で 8Mhz 動作するようになっているようです。従って 5V 動作をさせると発振周波数が高くなるので発声される声もピッチが上ると思われます。ということでロジックレベルの変換を入れまして、3.3V で動かしてみました。結論から言うとまぁ、そんなもんかなという感じでございます。

一つ目は、シリコンハウスで購入したレベル変換基板で BSS138 の MOSFET を使用したものです。写真では赤色の基板です。

もう一つは、デジットで買った TSX0102 をダイセンの変換にハンダ付けしたものです。写真では緑色の基板です。

まぁ、どちらでも問題無く動作確認完了です。

大阪市内で買い物

今日は 5V – 3.3V の変換は欲しかったので sparkfun のレベルコンバータ(基板実装済み)と、デジットで TXS0102 の Voltage-Level Translator を購入。あとは、細々した補充しておこうというものを購入しました。sparkfun のレベルコンバーターは BSS138 N-ch MOSFET を使ったもので、I2C の説明書などにもある MOSFET を使った電圧変換回路です。

次は梅田のササヤ書店さんで、ヴァイオリンの教本を購入。これを使用する先生は少ないと思いますが、3ポジに慣れるのに手頃でしょうということで勧めていただき購入することにしました。

AquesTalk pico ATP3011F1-PU に時間をしゃべってもらった。

今回は、Arduino UNO に EtherNet シールドを載せまして、サンプルスケッチの UDP NTP クライアントから採取した時刻から、無限ループで時間をしゃべってもらう部分の作成を行ないました。以下に動作させてみた例とソースを貼り付けておきます。

AquesTalk pico のコマンドには数字読み上げコマンドというのがあって <NUMK VAL=数字> というコマンドで何十というしゃべりもしてくれるので、ある程度手抜き出来そうです。動画はピンボケてますが、Q3HDの焦点距離とコンパクト三脚の高さの問題ですので仕方ありません。

#include
#include
#include
#include
#include

byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
unsigned int localPort = 8888;
IPAddress timeServer(192, 43, 244, 18); // time.nist.gov NTP server
const int NTP_PACKET_SIZE= 48;
byte packetBuffer[ NTP_PACKET_SIZE];
EthernetUDP Udp;
#define I2CPICO 0x2E

void setup() {
Wire.begin();
if (Ethernet.begin(mac) == 0) {
Serial.println(“Failed to configure Ethernet using DHCP”);
// no point in carrying on, so do nothing forevermore:
for(;;)
;
}
Udp.begin(localPort);
}

void loop() {
char tt[128];

sendNTPpacket(timeServer);
delay(1000);
if ( Udp.parsePacket() ) {
Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord; const unsigned long seventyYears = 2208988800UL; unsigned long epoch = secsSince1900 - seventyYears; int hh = ((epoch % 86400L) / 3600) + 9; switch(hh) { case 24: hh = 0; break; case 25: hh = 1; break; case 26: hh = 2; break; case 27: hh = 3; break; case 28: hh = 4; break; case 29: hh = 5; break; case 30: hh = 6; break; case 31: hh = 7; break; case 32: hh = 8; break; } int mm = (epoch % 3600) / 60; int ss = epoch % 60; sprintf(tt,"i'mano/ji'kokuwa ji fun byo’-de_su. \r”,hh,mm,ss);
AquesTalkPico_Send(tt);
}
delay(15000);
}

void AquesTalkPico_Ready() {

while(1) {
Wire.requestFrom(I2CPICO, 1); // request 1 byte
if(Wire.available() > 0) {
if(Wire.read() == ‘>’) break;
}
delay(50); // delay 50ms
}
}

void AquesTalkPico_Send(char *msg) {
unsigned char i;
char *smsg;

smsg = msg;
AquesTalkPico_Ready();
while(*smsg != 0) {
Wire.beginTransmission(I2CPICO);
for(i = 0; i < 32; i++) { Wire.write(*smsg++); if(*smsg == 0) { break; } } Wire.endTransmission(); } } unsigned long sendNTPpacket(IPAddress& address) { memset(packetBuffer, 0, NTP_PACKET_SIZE); packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; Udp.beginPacket(address, 123); //NTP requests are to port 123 Udp.write(packetBuffer,NTP_PACKET_SIZE); Udp.endPacket(); } [/code]