秋月VFDにRSSやTwitterの内容を表示させます。
電車内の広告のような物が作れます。
TwitterはTwitterAPIを使うことで、ぶつやきの内容をRSSとして配信することができます。
例
http://search.twitter.com/search.atom?q=IVRC つぶやきをIVRCで検索した結果
http://search.twitter.com/search.atom?q=from%3AIVRC ユーザーIVRCのつぶやき一覧
http://search.twitter.com/search.atom?q=%23IVRC ハッシュタグ#IVRCのつぶやき一覧
フォーム、ラジオボタン、ボタンをダブルクリックし、イベントを登録します
2 F5ボタンを押し、プログラムを実行します。
3 GP1022かGP1058、自分が使用しているVFDの型番を選択します。
4 VFDが接続されているCOMポートを選び、接続ボタンを押します。

5 小坂研究室のニュース一覧がVFDに表示されます。最後まで表示するとまた最初から表示しなおします。
6 「http://twitter.com/search.atom=%23okachan_sorry」をテキストボックスに貼り付け、追加ボタンをおします


7 小坂研究室のニュース表示が終わると、Twitterハッシュタグ#okachan_sorryの一覧を表示し始めます。

8 Twitterの表示が終わると、また小坂研究室のニュース表示を開始します。
9 切断を押して終了します。
タイマ
接続ボタンを押すと、1秒間隔でタイマ割り込みを発生させます
this.timer.Interval = 1000;
this.timer.Tick += new EventHandler(timer_Tick);
this.timer.Start();
また、シリアルVFDからデータを受信すると、割り込みを発生させるようにします。
this.serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
タイマ割り込みが入ると、コマンド0x1Cを送信します。
コマンド0x1CはVFDの表示動作を確認するコマンドです。
スクロール中であればVFDから0xC2,スクロール停止中ならC0が送られてきます
コマンド応答
VFDから送られてくる応答フレームは

のような構成になっています。
バッファが7バイト以上溜まったら、7バイトづつ読み込んで、3バイト目をチェックしています
void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] byteRcv = new byte[7];
if (this.serialPort.BytesToRead >= 7)//7バイト以上バッファが溜まったら
{
this.serialPort.Read(byteRcv, 0, 7);//7バイトづつ読み込む
if (byteRcv[2] == 0xC0)//スクロール停止中なら
XML
選択されているlistBoxのURLをXMLとして読み込みます
XmlReader reader = XmlReader.Create(this.listBox1.Items[this.listBox1.SelectedIndex] as String);
XmlDocument xd = new XmlDocument();
xd.Load(reader);
XML内の<title>タグ内で囲まれた項目をリストアップしています
XmlNodeList Nodes = xd.GetElementsByTagName("title");
XMLの項目を1つのStringに格納して、表示します
for (int i = 1; i < Nodes.Count; i++)//サイト名を表示する場合はi = 0から
{
if (i > 10) break;//10個以上は表示しない
sendMessage = sendMessage + " " + Nodes[i].InnerXml;
}
this.send_Message(sendMessage);
電車内の広告のような物が作れます。
TwitterはTwitterAPIを使うことで、ぶつやきの内容をRSSとして配信することができます。
例
http://search.twitter.com/search.atom?q=IVRC つぶやきをIVRCで検索した結果
http://search.twitter.com/search.atom?q=from%3AIVRC ユーザーIVRCのつぶやき一覧
http://search.twitter.com/search.atom?q=%23IVRC ハッシュタグ#IVRCのつぶやき一覧
1.プロジェクトの作成
Visual C#で「VFDTest」というWindowsフォームアプリケーションの新規プロジェクトを作成します。2.フォームの作成
フォーム上に、以下のようにコントロールを配置します
フォーム、ラジオボタン、ボタンをダブルクリックし、イベントを登録します
3.文字表示プログラム
form1.csに以下のプログラムを貼り付けますusing System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO.Ports; using System.Collections; using System.Net; using System.Xml; namespace VFDTest { public partial class Form1 : Form { private SerialPort serialPort = new SerialPort(); private Boolean is58 = false; private Timer timer = new Timer(); public Form1() { InitializeComponent(); this.serialPort = new SerialPort(); } //フォームロード private void Form1_Load(object sender, EventArgs e) { this.comboBox1.DropDownStyle = ComboBoxStyle.DropDownList; string[] ports = SerialPort.GetPortNames(); foreach (string port in ports) { this.comboBox1.Items.Add(port); } this.comboBox1.SelectedIndex = 0; //ラジオボタン this.radioButton1.Checked = true; this.is58 = false; //ボタン無効 this.button2.Enabled = false; this.button3.Enabled = false; //URLを追加 this.listBox1.Items.Add("http://www.kosaka-lab.com/kosaka_laboratory/atom.xml"); this.listBox1.SelectedIndex = 0; //他スレッドからのコントロール呼び出し許可 Control.CheckForIllegalCrossThreadCalls = false; } //接続 private void button1_Click(object sender, EventArgs e) { try { this.serialPort.BaudRate = 19200;//通信速度 19200bps this.serialPort.PortName = (string)this.comboBox1.SelectedItem;//ポート番号はコンボボックスから選択 this.serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived); this.serialPort.Open();//ポートオープン //GP1058の場合 if (this.is58 == true) { //画素数336x24 this.send_commandFrame(0x25, 0x00); } } catch (Exception ex) { //ポートオープンに失敗 MessageBox.Show(ex.ToString()); return; } //ボタン各種有効、無効 this.radioButton1.Enabled = false; this.radioButton2.Enabled = false; this.comboBox1.Enabled = false; this.button1.Enabled = false; this.button2.Enabled = true; this.button3.Enabled = true; //タイマー this.timer.Interval = 1000; this.timer.Tick += new EventHandler(timer_Tick); this.timer.Start(); } //VFDからの返答 void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { byte[] byteRcv = new byte[7]; if (this.serialPort.BytesToRead >= 7)//7バイト以上バッファが溜まったら { this.serialPort.Read(byteRcv, 0, 7);//7バイトづつ読み込む if (byteRcv[2] == 0xC0)//スクロール停止中なら { string sendMessage = ""; XmlReader reader = XmlReader.Create(this.listBox1.Items[this.listBox1.SelectedIndex] as String); XmlDocument xd = new XmlDocument(); xd.Load(reader); XmlNodeList Nodes = xd.GetElementsByTagName("title"); for (int i = 1; i < Nodes.Count; i++)//サイト名を表示する場合はi = 0から { if (i > 10) break;//10個以上は表示しない sendMessage = sendMessage + " " + Nodes[i].InnerXml; } this.send_Message(sendMessage); //次に表示するアイテムを変更 if (this.listBox1.SelectedIndex == this.listBox1.Items.Count - 1) { this.listBox1.SelectedIndex = 0;//最初から }else{ this.listBox1.SelectedIndex++; } } } } //切断 private void button2_Click(object sender, EventArgs e) { //ポートクローズ this.serialPort.Close(); //ボタン各種有効、無効 this.radioButton1.Enabled = true; this.radioButton2.Enabled = true; this.comboBox1.Enabled = true; this.button1.Enabled = true; this.button2.Enabled = false; //タイマ-ストップ this.timer.Stop(); } //コマンドフレーム送信 private void send_commandFrame(byte command, byte frame) { byte[] send = new byte[7]; byte[] byteSum = new byte[2]; send[2] = command; send[3] = frame; int nSum = send[0] + send[1] + send[2] + send[3]; byteSum = BitConverter.GetBytes(nSum); send[4] = byteSum[1]; send[5] = byteSum[0]; send[6] = 0xEF; if (this.serialPort.IsOpen == true) { try { this.serialPort.Write(send, 0, send.Length); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } //テキスト送信 private void send_Message(String message) { byte[] sendMessage = new byte[256]; //シフトjis->jis byte[] byteMessage = Encoding.GetEncoding(50220).GetBytes(message); //jis->vfd漢字ロムコード byte[] vfdCode = toVFDCode(byteMessage); int nFrame = vfdCode.Length / 256 + 1; if (vfdCode.Length > 4096) { Console.WriteLine("エラー:文字数オーバー"); return; } this.send_commandFrame(0x04, (byte)nFrame); //FFHで埋める for (int i = 0; i < 256; i++) { sendMessage[i] = 0xff; } int frameCount = 0; int byteCount = 0; for (int i = 0; i < vfdCode.Length; i++) { sendMessage[byteCount] = vfdCode[i]; byteCount++; if (byteCount == 256 || i == vfdCode.Length - 1) { frameCount++; byteCount = 0; this.send_dataFrame(sendMessage, (byte)frameCount); //FFHで埋める for (int j = 0; j < 256; j++) { sendMessage[j] = 0xff; } } } } //データフレーム送信 private void send_dataFrame(byte[] message, byte frame) { byte[] send = new byte[262]; byte[] byteSum = new byte[2]; //アドレス send[0] = 0x00; //フレーム番号 send[1] = frame; //コマンド send[2] = 0x00; //メッセージ for (int i = 3; i < 256 + 3; i++) { send[i] = message[i - 3]; } //サム計算 int nSum = 0; for (int i = 0; i < 256 + 3; i++) { nSum += send[i]; } byteSum = BitConverter.GetBytes(nSum); //SUM send[259] = byteSum[1]; send[260] = byteSum[0]; //END send[261] = 0xEF; if (this.serialPort.IsOpen == true) { this.serialPort.Write(send, 0, send.Length); } } //文字コード変換 jis->VFD独自コード private byte[] toVFDCode(byte[] jisCode) { ArrayList arrayVFDCode = new ArrayList(); byte[] byteVFDCode; Boolean isAscii = true; for (int i = 0; i < jisCode.Length; i++) { //アスキー、jis切り替え if (jisCode.Length - i >= 2) { if (jisCode[i] == 0x1b && jisCode[i + 1] == 0x24 && jisCode[i + 2] == 0x42) { isAscii = false; i += 2; continue; } else if (jisCode[i] == 0x1b && jisCode[i + 1] == 0x28 && jisCode[i + 2] == 0x42) { isAscii = true; i += 2; continue; } } if (isAscii) { //アスキーコード short tmp1, tmp2; tmp1 = jisCode[i]; tmp2 = (short)(tmp1 & 0xE0); tmp2 = (short)(tmp2 >> 5); tmp2--; tmp2 = (short)(tmp2 << 7); tmp1 = (short)(tmp1 & 0x1f); tmp2 = (short)(tmp2 | tmp1); tmp2 = (short)(tmp2 | 0x4000); tmp1 = (short)(tmp2 & 0x00FF); tmp2 = (short)(tmp2 >> 8); arrayVFDCode.Add((byte)tmp1); arrayVFDCode.Add((byte)tmp2); } else { short tmp1 = jisCode[i], tmp2 = jisCode[i + 1], tmp4 = 0; int flag = jisCode[i] >> 4; switch (flag) { case 2: //非漢字 tmp1 = (short)(tmp1 & 0x7F); tmp4 = (short)(tmp1 & 0x7); tmp1 = (short)(tmp2 >> 2); tmp1 = (short)(tmp1 & 0x18); tmp1 = (short)(tmp1 | tmp4); tmp1 = (short)(tmp1 << 7); tmp1 = (short)(tmp1 & 0xF9F); tmp2 = (short)(tmp2 & 0x1F); tmp2 = (short)(tmp2 | tmp1); tmp2 = (short)(tmp2 & 0xFFF); break; case 3: case 4: //3:漢字第一水準1 4:漢字第一水準2 tmp1 = (short)(tmp1 & 0x7F); tmp4 = (short)(tmp1 & 0xF); tmp1 = (short)(tmp1 >> 2); tmp1 = (short)(tmp1 & 0x30); tmp1 = (short)(tmp1 | tmp4); tmp1 = (short)(tmp1 << 7); tmp2 = (short)(tmp2 & 0x7F); tmp2 = (short)(tmp2 | tmp1); tmp2 = (short)(tmp2 & 0xFFF); break; case 5: case 6: //5:漢字第二水準1 6:漢字第二水準2 tmp1 = (short)(tmp1 & 0x7F); tmp4 = (short)(tmp1 & 0xF); tmp1 = (short)(tmp1 >> 1); tmp1 = (short)(tmp1 & 0x10); tmp1 = (short)(tmp1 | tmp4); tmp1 = (short)(tmp1 << 7); tmp2 = (short)(tmp2 & 0x7F); tmp2 = (short)(tmp2 | tmp1); tmp2 = (short)(tmp2 | 0x1000); break; case 7: //漢字第二水準3 tmp1 = (short)(tmp1 & 0x7F); tmp4 = (short)(tmp1 & 0x7); tmp1 = (short)(tmp2 >> 2); tmp1 = (short)(tmp1 & 0x18); tmp1 = (short)(tmp1 | tmp4); tmp1 = (short)(tmp1 << 7); tmp2 = (short)(tmp2 & 0x1F); tmp2 = (short)(tmp2 | tmp1); tmp2 = (short)(tmp2 | 0x1000); break; default: //その他 //スルー continue; } tmp1 = (short)(tmp2 & 0x00ff); tmp2 = (short)(tmp2 >> 8); //リストに追加 arrayVFDCode.Add((byte)tmp1); arrayVFDCode.Add((byte)tmp2); //2バイト分進めるために、先に+1しておく i++; } } byteVFDCode = new byte[arrayVFDCode.Count]; for (int i = 0; i < arrayVFDCode.Count; i++) { byteVFDCode[i] = (byte)arrayVFDCode[i]; } return byteVFDCode; } //ラジオボタン private void radioButton1_CheckedChanged(object sender, EventArgs e) { this.is58 = false; } //ラジオボタン private void radioButton2_CheckedChanged(object sender, EventArgs e) { this.is58 = true; } //巡回リスト追加 private void button3_Click(object sender, EventArgs e) { this.listBox1.Items.Add(textBox1.Text); this.textBox1.Text = "";//テキストボックスクリア } //タイマーイベント void timer_Tick(object sender, EventArgs e) { this.send_commandFrame(0x1c, 0x00);//スクロール中かどうか判断する } } }
実行
1 VFDに電源を入れ、PCに繋ぎます。2 F5ボタンを押し、プログラムを実行します。
3 GP1022かGP1058、自分が使用しているVFDの型番を選択します。
4 VFDが接続されているCOMポートを選び、接続ボタンを押します。

5 小坂研究室のニュース一覧がVFDに表示されます。最後まで表示するとまた最初から表示しなおします。
6 「http://twitter.com/search.atom=%23okachan_sorry」をテキストボックスに貼り付け、追加ボタンをおします


7 小坂研究室のニュース表示が終わると、Twitterハッシュタグ#okachan_sorryの一覧を表示し始めます。

8 Twitterの表示が終わると、また小坂研究室のニュース表示を開始します。
9 切断を押して終了します。
解説
VFDにRSSの文字を表示します。タイマ
接続ボタンを押すと、1秒間隔でタイマ割り込みを発生させます
this.timer.Interval = 1000;
this.timer.Tick += new EventHandler(timer_Tick);
this.timer.Start();
また、シリアルVFDからデータを受信すると、割り込みを発生させるようにします。
this.serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
タイマ割り込みが入ると、コマンド0x1Cを送信します。
コマンド0x1CはVFDの表示動作を確認するコマンドです。
スクロール中であればVFDから0xC2,スクロール停止中ならC0が送られてきます
コマンド応答
VFDから送られてくる応答フレームは

のような構成になっています。
バッファが7バイト以上溜まったら、7バイトづつ読み込んで、3バイト目をチェックしています
void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] byteRcv = new byte[7];
if (this.serialPort.BytesToRead >= 7)//7バイト以上バッファが溜まったら
{
this.serialPort.Read(byteRcv, 0, 7);//7バイトづつ読み込む
if (byteRcv[2] == 0xC0)//スクロール停止中なら
XML
選択されているlistBoxのURLをXMLとして読み込みます
XmlReader reader = XmlReader.Create(this.listBox1.Items[this.listBox1.SelectedIndex] as String);
XmlDocument xd = new XmlDocument();
xd.Load(reader);
XML内の<title>タグ内で囲まれた項目をリストアップしています
XmlNodeList Nodes = xd.GetElementsByTagName("title");
XMLの項目を1つのStringに格納して、表示します
for (int i = 1; i < Nodes.Count; i++)//サイト名を表示する場合はi = 0から
{
if (i > 10) break;//10個以上は表示しない
sendMessage = sendMessage + " " + Nodes[i].InnerXml;
}
this.send_Message(sendMessage);

