SyntaxHighlighter

2015年3月27日金曜日

#FlashAir をいじっている記録

※本情報は、参考のために残しており、古い情報を含みます。
 現在主に更新しているのはwikiですので、最新の情報はwikiを参照してください。

---
現在進行形でいじってるので、ブログにまとめるのも面倒
ということで、Togetterのほうに適時まとめてます。

FlashAirをいじった記録 - Togetterまとめ http://togetter.com/li/800274

いじりながらつぶやいていることをまとめているので、誤りや
誤解、愚痴など混ざっていますので、参考にされる場合ご注意ください。

だって、他の人がLua使えるSDカードとしていじってる話、全然聞かないんだもの。

2015年3月25日水曜日

FlashAir上でLuaスクリプトのエラーを表示する

FlashAir III(W-03)でLuaスクリプトを動かす際、一番厄介なのは エラーメッセージが出力されないことだと思います。 文法ミス1つでもあればこう。
昔懐かしいCGIのよう。

PC上で試しに動かしてから書き込めばいいのですが、それも面倒といえば面倒。 しかし、Luaにはpcallという、エラーをハンドリングする機能があります。 それを使ってやると、FlashAir側には正常なように処理しつつ、Luaのエラーを ブラウザに出力することができます。 まず、debug.luaとして以下のものを用意。 f = loadfile("body.lua") local flag, ret = pcall(f) if not flag then
   print("HTTP/1.1 500 Internal Server Error\n\n") print("<pre>") print("!!! Lua error detected.!!!\n") print("------------\n") print(ret) print("\n------------\n") print("</pre>") else print("<!-- OK -->") end 次に、デバッグしたいLuaファイルをbody.luaとして用意。 ここでは以下のものをサンプルとして用意 print("<HTML><HEAD><TITLE>Hello World!!</TITLE>") print("<BODY><H1>Hello World!</H1>") error("Hell World") print("Have a nice day!") print("</body></html>") これらを同じフォルダに置き、debug.luaを実行。 ここでは、body.luaのほうにerror関数があるので、実行中にエラーが発生します。 そのため、body.lua単体で実行すると尻切れトンボになりますが debug.luaを通して実行すると
このようにエラー内容が表示されて停止します。 また、body.luaを次のようにしてみます。 print("WoW") HELLO print("WoW") body.luaを直接実行すると、HELLOが文法エラーのため、なにも実行されずに停止します。 debug.luaを通して実行すると
のように表示されます。 いかがでしょうか。 printの代わりにファイルに出力するようにすれば、自動実行や書き込み時実行の luaファイルも同様にデバッグ可能になると思います。 参考になると幸いです。

ちなみに、この機能も含めてブラウザ上で動く簡易IDEがあります。
https://sites.google.com/site/gpsnmeajp/tools/flashair_tiny_lua_editer

FlashAirで遊んだ記録

※本情報は、参考のために残しており、古い情報を含みます。
 現在主に更新しているのはwikiですので、最新の情報はwikiを参照してください。

---
FlashAir III (W-03)で遊んだ結果をいろいろ追記していこうと思う。

1.自動起動スクリプトの注意点
FlashAirをアクセスポイントに接続するモードにした場合、接続までにそこそこ
時間がかかる。そのため、電源投入時に即LuaスクリプトからHttpアクセスしようとすると
たいてい失敗する。

30秒ほど待つとよい。


2.Luaスクリプトと無線スリープ
適当に、起動してから1秒置きに経過時間を書き込むLuaスクを書いてほっといたところ
いつまでも動作が続く。
無線LAN側から見えなくなっても続く。
タイムアウトに関係ないようだ。


3.ファイル破損
なにかを誤ったのか、ドライブが破損している的なメッセージをWindowsが発するようになった。
CHKDSKをしろと言われるが、過去の経験からあまりよろしくない。
特に大事なデータが入っているわけでもないのでフォーマットすることにした。

東芝ツールから初期化→ダメ (設定の初期化しかされない?)

松下SDフォーマッタからイレースフォーマット
↓(まっさらに)
東芝ツール起動
↓(ドライブ指定しろ→再度差し込め)
  どうやらCONFIGファイルを作成してバージョン情報を
  書き込ませている模様。
東芝ツールから初期化

退避しておいたCONFIGファイルをコピペ

で復旧した。


4.Pomera DM100の挙動
Windowsでは、Luaスクリプトから書き換えられたファイルをリアルタイムに見ることはできず、
差し直し(おそらく再マウントでよいと思うが)しなければならない。

しかし、Pomeraでは、Luaスクリプトから書き換えられたテキストを
開きなおすたびに最新の情報が表示される。

つまり、テキストWebブラウザくらいのことはできるということだ。

2015年3月18日水曜日

バックグラウンドでもFlashゲームを高速動作させる

最近刀剣乱舞をやっていて気が付いたが、タブの後ろや
ウィンドウの後ろにあるFlashは、バックグラウンド用に速度を抑えるようだ。

刀剣乱舞では、戦闘時の動作が明らかに遅くなる
(効果音の間隔が長くなる・索敵に時間がかかる、など)

これを回避する方法を見つけたので記しておく。
といっても、参考文献のそのままだが、一部パスが違うので記録しておく。

32bit版Windowsの場合、以下の場所にファイルを作成する。
(すでに存在する場合はそこに追記する。)
C:\windows\system32\macromed\flash\mms.cfg
メモ帳を『管理者権限で起動』するのが良い。

そして、最後の行に以下を追記する。
FullFramerateWhenInvisible=1

64bit版Windowsの場合、以下の場所にも同様に作成・追記する。
C:\windows\syswow64\macromed\flash\mms.cfg

GoogleChromeを使用している場合、以下の場所にも同様に作成・追記する。
C:\Users\ユーザー名\AppData\Local\Google\Chrome\User Data\Default\Pepper Data\Shockwave Flash\System\mms.cfg
(Windows 8.1 Updateの場合のパスである。他のOSでは場所が変わる場合がある)

ちなみに、Systemフォルダ自体存在しないので、注意
つまり、
C:\Users\ユーザー名\AppData\Local\Google\Chrome\User Data\Default\Pepper Data\Shockwave Flash\
に移動後、Systemフォルダを作成し、mms.cfgを作成することになる。


参考文献
バックグラウンド再生でもFlashをすばやく動かす方法 

Windows/バックグラウンドのFlashの動作を止めない方法 - Yunacci-Wiki 

2015年3月9日月曜日

IchigoJamのIOポートに繋ぐと便利そうなもの

IchigoJamはまだ持っていないが、繋ぐと便利そうなものをリストアップしてみる
(=マイコンの心得がなくても使えそうなもの)

参考になれば

*PICアクチュエーター・キット: 組み立てキット 秋月電子通商 電子部品 ネット通販
指定した2つの角度にサーボモーターを動かすことができる。
2つのボタン操作の代わりに外部回路をつなぐことができる。
http://akizukidenshi.com/catalog/g/gK-01809/

*DRV8832使用DCモータードライブキット: 半導体 秋月電子通商 電子部品 ネット通販
モーターの制御ができる。
IN1,IN2の端子を操作することで、正転・逆転・停止ができる。
速度変更はボリュームで。
http://akizukidenshi.com/catalog/g/gK-06497/

*高精度IC温度センサ LM35DZ: センサ一般 秋月電子通商 電子部品 ネット通販
アナログ入力端子を使って温度が測れる
http://akizukidenshi.com/catalog/g/gI-00116/

*5ポジションスイッチ・モジュール #27801: パーツ一般 秋月電子通商 電子部品 ネット通販
プルアップ済み。入力端子につないでゲーム機みたいに。
http://akizukidenshi.com/catalog/g/gM-06808/

*大電流大型リレーモジュールキット: パーツ一般 秋月電子通商 電子部品 ネット通販
蛍光灯とか、モーターとか、とりあえずON-OFF制御したいときに
http://akizukidenshi.com/catalog/g/gK-06095/

*ZigBeeワイヤレスモジュール TWE-Lite Dip-WA (半完成品セミキット): 無線、高周波関連商品 秋月電子通商 電子部品 ネット通販
とりあえずデジタルIO入出力を無線化できる。
http://akizukidenshi.com/catalog/g/gK-06759/

*光センサースイッチキット: 組み立てキット 秋月電子通商 電子部品 ネット通販
明るいか暗いかをON-OFFで知ることができる
(個人的には、CdSと抵抗を用いて分圧し、アナログ入力につなぐのをお勧めするが、
 アナログ入力がふさがっているときなど)
http://akizukidenshi.com/catalog/g/gK-06623/

*PICマイコン赤外線リモコン学習キット: 組み立てキット 秋月電子通商 電子部品 ネット通販
スイッチ入力をトランジスタで置き換えてあげれば、
リモコン操作がBASICからできるようになる。
http://akizukidenshi.com/catalog/g/gK-04174/

*音声合成LSI - AquesTalk pico LSI
あらかじめ書き込んでおいた言葉を4bitのスイッチ入力で発声するモードがあるので
それを使えば15種類の声をIchigojamから鳴らせる
(ただし、書き込みにはPCとUSB-UART変換アダプタが必要。)
http://www.a-quest.com/products/aquestalkpicolsi.html

2015年3月7日土曜日

マイコン(Arduino等)とMindstorms NXT/EV3をI2Cで繋ぐ(プログラム)

デバイスに依存する一部の記述を書き換えれば、
たいていの環境で利用できるよう、1から書き直しました。
松原拓也様のNicosensorを参考にさせて頂いています。
#define scl0     10
#define sda0      9
#define ACK       0
#define NAK       1
#define WRITE     0
#define READ      1

#define SDA_OPEN  1
#define SDA_LOW   0
#define SCL_OPEN  1
#define SCL_LOW   0


void setup()
{
    main0();
}
void loop()
{}


//---デバイス依存部---
void iic_ports_low()
{
    digitalWrite(scl0,LOW);
    digitalWrite(sda0,LOW);
}

void set_scl(char t)
{
    if(t==SCL_LOW)
        pinMode(scl0,OUTPUT);//Low
    else
        pinMode(scl0,INPUT);//Hi-Z

    return;
}
void set_sda(char t)
{
    if(t==SDA_LOW)
        pinMode(sda0,OUTPUT);//Low
    else
        pinMode(sda0,INPUT);//Hi-Z

    return;
}
char get_scl()
{
  return digitalRead(scl0);
}
char get_sda()
{
  return digitalRead(sda0);
}
//--------------------------

void iic_bus_open()
{
    iic_ports_low();
    set_scl(SCL_OPEN);set_sda(SDA_OPEN);    
}
void iic_wait_scl(unsigned char b_scl)
{
    while(!(get_scl() == b_scl));    
}

void iic_wait_bus(unsigned char b_sda,unsigned char b_scl)
{
    while(!(get_sda() == b_dsa && get_scl() == b_scl));
}


void iic_start()
{
    iic_bus_open();    
    iic_wait_bus(SDA_OPEN,SCL_OPEN);
    iic_wait_bus(SDA_LOW ,SCL_OPEN);
    iic_wait_bus(SDA_LOW ,SCL_LOW);
}

void iic_stop()
{
    iic_bus_open();    
    iic_wait_bus(SDA_OPEN,SCL_OPEN);
}

void iic_set_ack(char ack_or_nak)
{
    //0=ack, 1=nak
    set_sda(ack_or_nak);
    iic_wait_scl(SCL_OPEN);    
    iic_wait_scl(SCL_LOW);
}

unsigned char iic_write(unsigned char d)
{
    int i;
    int ack = 0;
    for(i=0;i<8;i++)
    {
        if((d & 0x80) != 0)
            set_sda(SDA_OPEN);
        else
            set_sda(SDA_LOW);
            
        d<<=1;
        iic_wait_scl(SCL_OPEN);    
        iic_wait_scl(SCL_LOW);
    }
//--
//0=ack, 1=nak

    set_sda(SDA_OPEN);
    iic_wait_scl(SCL_OPEN);        

    if(get_sda() != 0)
        ack = 1;

    iic_wait_scl(SCL_LOW);    

    return ack;
}
unsigned char iic_read()
{
    int i;
    unsigned char d = 0;

    for(i=0;i<8;i++)
    {
        d<<=1;

        iic_wait_scl(SCL_OPEN);    

        if(get_sda() != 0)
            d |= 1;            

        iic_wait_scl(SCL_LOW);
    }
    return d;
}

//アドレスだけほしい時
unsigned char iic_start_and_wait()
{
        iic_start();
        return iic_read();    
}

//1つのアドレスのみ反応したいとき
void iic_start_and_wait_for_me(unsigned char adr,char mode)
{
    //0=write 1=read
    unsigned char radr = 0;
    unsigned char cadr = ((adr << 1) & 0xFE)|mode;
    while(1){
        radr = iic_start_and_wait();
        
        if(radr == cadr)
            break;

        iic_set_ack(NAK);        
    }
    
    iic_set_ack(ACK);
    return;
}


#define MODE_NXT_READ_NON_REG    0
#define MODE_NXT_READ_REG        1

#define MODE_NXT_WRITE_NON_REG   2
#define MODE_NXT_WRITE_REG       3

#define MODE_EV3_1_BYTE_WRITE    4
#define MODE_EV3_1_BYTE_READ     5

#define MODE_EV3_8_BYTE_WRITE    6
#define MODE_EV3_8_BYTE_READ     7

void main0()
{
    int c,ack;
    unsigned char reg=0,reg_ary[8]={0},val=0,val_ary[8]={0};
    iic_bus_open();    
    delay(100);
    
    
    mode = x;
    
    while(1)
    {
        switch(mode)
            case MODE_NXT_READ_NON_REG:
                iic_start_and_wait_for_me(0x01,WRITE);

                iic_start_and_wait(0x01,READ);
                ack = iic_write(val);

                iic_stop();
                break;
            case MODE_NXT_READ_REG:
                iic_start_and_wait_for_me(0x01,WRITE);

                reg=iic_read();
                iic_set_ack(ACK);

                iic_start_and_wait(0x01,READ);
                ack = iic_write(val);            

                iic_stop();
                break;
            case MODE_NXT_WRITE_NON_REG:
                iic_start_and_wait_for_me(0x01,WRITE);

                val=iic_read();
                iic_set_ack(ACK);

                iic_stop();
                            break;
            case MODE_NXT_WRITE_REG:
                iic_start_and_wait_for_me(0x01,WRITE);

                reg=iic_read();
                iic_set_ack(ACK);
                val=iic_read();
                iic_set_ack(ACK);

                iic_stop();            
                break;

            case MODE_EV3_1_BYTE_READ:
                iic_start_and_wait(0x01,READ);
                ack = iic_write(val);            

                iic_stop();            
                break;
            case MODE_EV3_1_BYTE_WRITE:
                iic_start_and_wait_for_me(0x01,WRITE);

                val=iic_read();
                iic_set_ack(ACK);

                iic_stop();
                break;
            case MODE_EV3_8_BYTE_READ:
                iic_start_and_wait(0x01,READ);
                for(i=0;i<8;i++)
                    ack = iic_write(val[i]);
                iic_stop();            
                break;
            case MODE_EV3_8_BYTE_WRITE:
                iic_start_and_wait(0x01,READ);
                for(i=0;i<8;i++)
                {
                    reg[i]=iic_read();
                    iic_set_ack(ACK);
                }
                iic_stop();            
                break;
        
            iic_start_and_wait_for_me(0x01,WRITE);
            c=iic_read();
            iic_set_ack(ACK);
//            iic_set_ack(NAK);
            
//            iic_start_and_wait(0x01,READ);
                        iic_start();
            iic_read();
            iic_set_ack(ACK);
            ack = iic_write(5);
            iic_stop();
    }
    
}


void NXT_EV3_1BYTE_READ() //NXT=RegありREAD,EV3=1byteREAD
{
    int c,ack,adr;
    unsigned char val=0;
    iic_bus_open();    
    delay(100);
    
    while(1)
    {
        adr = iic_start_and_wait();

        if(adr == 0x01|READ)
        {
            iic_set_ack(ACK);

            ack = iic_write(val);            
            iic_stop();
        }else if(adr == 0x01|WRITE)
        {
            iic_set_ack(ACK);

            iic_read();
            iic_set_ack(ACK);
        }else{
            iic_set_ack(NAK);            
        }
    }    
}

2015年3月6日金曜日

マイコン(Arduino等)とMindstorms NXT/EV3をI2Cで繋ぐ

マイコンをセンサーとしてMindstorms NXT/EV3を繋ぐ方法について記す。 英語/日本語の資料をバタバタと行き来して大変だったため。 1.接続方法(物理層) マイコンとMindstorms を接続する方法は、NXTでは3つ、EV3では6つある。 ・Bluetooth ・アナログ ・I2C ・UART (EV3のみ) ・LAN (EV3のみ) ・USB (EV3のみ) このうち、LAN・Bluetoothはセンサーではなく、ホストとしての接続となる。 USBはEV3をツリー接続できることから可能だろうと考えられるが、現状難しいと思われる。 UARTは、シリアルコンソールか、センサーの2種類があるが、 仕様をよく調査できなかったため、扱わない。 アナログ入力については、他の人の情報を参照してほしい。 ここでは、情報の多いI2C接続を用いる。 I2C接続は、公式にはNXTの超音波距離センサーにのみ使われている。 (他サードパーティのセンサーの多くはI2Cを使っている) EV3の超音波距離センサーはUART接続だ。 I2Cは、センサー入力の変形RJ12端子の、端の2ピンに出ている。 5pinにSCL、6pinにSDAが出ている。 この特殊コネクタは通常には手に入らない。 mindsensors社がほぼ唯一取り扱っており、この中では I2C Host Cable with NXT Connector http://www.mindsensors.com/index.php?module=pagemaster&PAGE_user_op=view_page&PAGE_id=136 がケーブル付きで使いやすい。(ピンの解説もここでしている) プラグのみ販売もしれいるが、圧着工具が特殊になる(市販の工具を改造して用いる必要がある)ので注意。 日本ではROBO Product社が扱っている。 http://roboproduct.com/MS02NXTAccessories.html わかりにくいが、2本1セットで525円である。 ちなみに、送料が1180円と高いので注意。買うなら多めに。 2.接続方法(回路・ソフトウェア) 最初は超音波距離センサー(Ultrasonic distance sensor)として接続するのをおすすめする。 超音波センサーであれば、容易にテストが可能だからだ。 I2C機器を直接扱う追加ブロックもあるが、後述する。 接続回路および、プログラムは、松原拓也のNicoSensorがわかりやすい。 I2Cスレーブをソフトウェアで実装しているため、安価な少ピンマイコンを使うことができる。 http://nicotak.com/robot/nxt/ Arduinoを用いる場合、相応のライブラリが公開されているようなので、そちらを用いるといいだろう。 通信プロトコルは、 LEGO MINDSTORMS NXT Ultrasonic Sensor I2C Communication Protocol で検索すればPDFファイルで出てくるが、少なくともNXTでは NicoSensorのように0x42命令にだけ対応していれば問題なく通信できる。

I2Cのクロック速度は10kHz以下と低速で、故にソフトウェアでも処理できる。
ただし、BrickPiなどは100kbpsで通信しようとするため、使用できない可能性がある。注意。

追記
自分の試した限り、NXTでは超音波距離センサーとして接続できたが
EV3では接続できなかった。接続開始時になにやら送信されているのが確認されたため、
これを解析すれば問題なく動くようにできるだろうが、
下記のカスタムブロックでは問題なく通信できているため、詳しくは調べていない。
3.周期など Mindstorm NXTで確認した感じだと、センサー入力で待機、 もしくはループの条件をセンサーにした場合、通信を含め47ms周期で取得が行われた。 通信のタイミングは、センサーの命令が発生した時である。 通信から次の通信までは43msである。 つまり、最高速でも40msの処理時間があり、さらにNXT側のプログラムで ウェイトを入れてあげれば、より処理時間が確保できる。 (実際1secのウェイトを入れると1040msほどになった)

追記
上記の結果は純正超音波距離センサーとしてつないだ場合で、
下記のカスタムブロックを用いると、NXT/EV3共に、10ms以下で取得ループが発生する。

NXTの場合、通信以外の余地は1msしか存在しなかった。

4.任意の通信をする C言語などを使えば任意の通信が可能なのは調べれば容易に出てくるが、 ブロックプログラミング(NXT-G等)を使って、任意のI2C機器と通信するにはどうするか。 以下の追加ブロックを使用すれば可能である。 EV3の場合、Dexter Industries EV3 SensorsのI2C communication blockを使う。 https://github.com/DexterInd/EV3_Dexter_Industries_Sensors ページ下部に書いてあるとおり、Dexter.ev3bをダウンロードし、インポート EV3ソフトウェアからインポートしてあげれば良い。 ※EV3ソフトウェアからNXTをプログラミングするときには使用できない (Program.ev3pが見つからないと表示される) 使い方は以下がいい。 http://www.dexterindustries.com/howto/connecting-ev3-arduino/ NXTの場合、Mindsensor社のIIC_Read.zip、IIC_Write.zipを用いる。 http://www.mindsensors.com/index.php?module=documents&JAS_DocumentManager_op=categories&category=12 解凍し、NXTソフトウェアから解凍したフォルダ内を指定してあげると、インポート項目に現れる。 (導入方法) http://www.mindsensors.com/index.php?module=pagemaster&PAGE_user_op=view_page&PAGE_id=81 5.各ブロックの使い方 I2CReadは次のように使う WriteRegを無効にした状態だと、下のようなプログラムで送信できる。 waitForMe(MYSLA); //(スタートビット&自分のアドレスまで待機) i2c_start(); //送受信切替 i2c_read_byte(); //Writeフラグのたったアドレスを破棄 i2c_write_ack(); // ACK送信 i2c_write_byte(val); // 値送信 i2c_get_ack(); i2c_stop(); WriteRegを有効にした状態だと、レジスタ、つまりアドレス指定ができるようになる。 実質的に1バイトのデータを送った返事として受け取るような形となる。 下のようなプログラムで送受信できる。 waitForMe(MYSLA); //(スタートビット&自分のアドレスまで待機) reg = i2c_read_byte(); //レジスタ受信 i2c_write_ack(); // ACK送信 i2c_start(); //送受信切替 i2c_read_byte(); //Writeフラグのたったアドレスを破棄 i2c_write_ack(); // ACK送信 i2c_write_byte(val); // 値送信 i2c_get_ack(); i2c_stop(); I2CWriteは次のように使う WriteRegを無効にした状態だと、下のようなプログラムで受信できる。 waitForMe(MYSLA); //(スタートビット&自分のアドレスまで待機) val = i2c_read_byte(); //値受信 i2c_write_ack(); // ACK送信 i2c_stop(); WriteRegを有効にした状態だと、レジスタ、つまりアドレス指定ができるようになる。 実質的に2バイトのデータを送ような形となる。 waitForMe(MYSLA); //(スタートビット&自分のアドレスまで待機) reg = i2c_read_byte(); //レジスタ受信 i2c_write_ack(); // ACK送信 val = i2c_read_byte(); //値受信 i2c_write_ack(); // ACK送信 i2c_stop(); ちなみにwaitForMeの中身を以下に示す。 Nicosensorのソースを切り出したそのままなので、そちらを参照していただきたい。 void waitForMe(unsigned char myadr) { unsigned char slaw=0; while(1){ i2c_start(); // 1.マスタからの接続待ち slaw = i2c_read_byte(); // 2.アドレス受信 if (slaw == myadr) { // アドレスが一致の場合、 i2c_write_ack(); // ACK送信 break; } else { // アドレスが不一致の場合、 i2c_write_nack(); // NACK送信 } } }
---

追記
EV3のDexterの場合、挙動が異なる。
アドレスの指定の仕方は7bitで、各ブロックで勝手にRead/Writeビットをセットしてくれる。
1を指定すると、書き込みは0x02、読み込みは0x03になる。

MindsensorのIIC_Read、IIC_Writeの場合、アドレス指定は8bitで行う。
こちらもRead/Writeビットをセットしてくれる。
2を指定すると、書き込みは0x02、読み込みは0x03になる。

が、このセットの仕方がORではなく+1のため、
例えば読み込みなのに1を指定すると、書き込みは0x01、読み込みは0x02とおかしなことになる。

また、読み込みに入るタイミングなどが違うので
各挙動については以下の図を参照してほしい。


追記
EV3のブロックのdigitalWriteは、I2CWriteのWriteRegを有効にした状態、
EV3のブロックのdigitalReadは、I2CReadのWriteRegを有効にした状態と等価に動く。

また、一部のI2C機器はEV3ではアナログセンサーと認識し、初回接続時動作しないことがある。
プログラム実行中に抜き差しするとEV3がI2C機器として認識しなおすため、動作するようになる。

TETRIXのDC Motor装置をEV3のブロックで動かすことができたので記録。


---
Arduinoで動作確認して、PICに移植している。 Arduinoでのソースがほしい方が居たら、お渡しできるので連絡してほしい。 以上、参考になれば嬉しい。 なにか追加の情報を持っている方が居たら、twitterまで知らせてほしい。
---



--- 関係ないが、GoogleDocsで編集したものを画像込みで コピペしたら、画像ごと貼り付けられた。下書きにはGoogleDocsが便利なようだ。 ただ、フォントが違うのがいただけない。

2015年3月3日火曜日

Windowsの画面の明るさを変えるバッチファイル

現在アクティブな電源プロファイルのGUIDを自動で取得するようにしました。
自分の使ってみた感じだと、複数のプロファイルを切り替えても動きました。
AC、DCの両方をセットするので、電源接続時でもバッテリー状態でも動きます。

D:\LIGHT_SET 10
とかいう感じで使ってみてください

---LIGHT_SET.bat---

@echo off

IF "%1"=="" (
SET /P LIGHT_LEVEL="明るさを入力してください(0~100)"
) ELSE (
SET LIGHT_LEVEL=%1
)

SET /A LIGHT_LEVEL=%LIGHT_LEVEL%
REM 数値かチェック(数値でなければ0になる)
REM 異常値チェックをしていないが、powercfg側が弾いてくれる。

REM 現在アクティブな電源プロファイルのGUIDを取得
FOR /f "DELIMS=" %%A IN ('Powercfg -getactivescheme') DO SET RAW_GUID=%%A
SET GUID=%RAW_GUID:~12,36%
ECHO GUID:%GUID%

powercfg -setACvalueindex %GUID% 7516b95f-f776-4464-8c53-06167f40cc99 aded5e82-b909-4619-9949-f5d71dac0bcb %LIGHT_LEVEL%
powercfg -setDCvalueindex %GUID% 7516b95f-f776-4464-8c53-06167f40cc99 aded5e82-b909-4619-9949-f5d71dac0bcb %LIGHT_LEVEL%
powercfg -setactive %GUID%

ECHO 明るさを%LIGHT_LEVEL%に設定した

EXIT /B 0

---

2015年3月2日月曜日

Windowsの画面の明るさをコマンドラインからいじる

Windows Vista以降から標準で搭載されたっぽい画面の明るさ制御を
コマンドからやる方法ってどうやるだろう、と調べたら
ばっちり書いてくれている人が居た。

Win32APIで画面の明るさを変更する方法 - Kerosoft : Modus Operandi http://mo.kerosoft.com/0192

1. Powercfg -getactivescheme でアクティブな電源管理のプロファイルIDを調べる。

自分の場合は以下のように表示された。
電源設定の GUID: 381b4222-f694-41f0-9685-ff5bb260df2e  (バランス)

PCごとに違う。注意。
また、多分1回調べれば、プロファイルを作りなおさない限り変わらない。
このPCの場合は381b4222-f694-41f0-9685-ff5bb260df2e


2.
powercfg -setACvalueindex <プロファイルID> 7516b95f-f776-4464-8c53-06167f40cc99 aded5e82-b909-4619-9949-f5d71dac0bcb <明るさ(0~100)>
powercfg -setDCvalueindex <プロファイルID> 7516b95f-f776-4464-8c53-06167f40cc99 aded5e82-b909-4619-9949-f5d71dac0bcb <明るさ(0~100)>

を実行した上で

powercfg -setactive <プロファイルID>

を実行する。
設定を変更して、適用するのと同じだ。

ACの方は電源接続時、DCのほうがバッテリー時である。
両方同じにする必要はないし、必要な方だけ設定すれば良い。


バッチファイルやタイマーから操作するときはこれでいいと思う。
プログラムからはWindows APIを使ったほうが良い。

今日の教訓

教訓: PICのPORTxレジスタのBSF,BCF問題はC言語でも変わらず生きている。
    入力ピンを念のため初期化するなら、一括で設定するか、別途変数を作る。

ちょっとわけあってこんなプログラムをPICのX8Cで組んでいました
PICを触るのはまた久しぶり、しかも短時間だからどんどん忘れている。

void digitalWrite(int p,int x)
{
    if(p == sda0)
    {
        RB4 = x;
    }else if(p == scl0){
        RB5 = x;
    }
}

void I2C_START_()
{
   digitalWrite(sda0,LOW);
   digitalWrite(scl0,LOW);

   pinMode(scl0,INPUT);

   ...

}


そうです、下にArduinoで組んだI2Cマスタをそのまま移植しています。
ここで問題、このプログラムは正常に動作するでしょうか?

解:しない

どういう挙動になるか?

*理想
RB4=0 でポートB4が LOWに。
RB5=0 でポートB5が LOWに。

ポートは入力に設定されているので、直ぐに出力には影響しないが
ポートを入力にするとHi-Z、出力にするとLowになる。

*現実
RB4=0 でポートB4が LOWに。
出力・入力レジスタが共有で、BCFで書き換わるため
読み出し→書き換え→書き込みが行われるため、プルアップされているRB5がHIGHに

RB5=0 でポートB5が LOWに。
出力・入力レジスタが共有で、BCFで書き換わるため
読み出し→書き換え→書き込みが行われるため、プルアップされているRB4がHIGHに

ポートは入力に設定されているので、直ぐに出力には影響しないが
ポートを入力にするとRB4、RB5ともにHi-Z

出力にするとRB4がHigh、RB5がLowになる。


そりゃうまく動かないわけだ。

しかも、お陰で3.3Vで動いているLCDの入力ピンに5Vを掛けたことに。
とりあえず、時間が短かったせいか壊れてはいないようです。

*解決方法
void digitalWrite(int p,int x)
{
   PORTB=0; //他なにもつながってないし
}

AVRでは入出力のレジスタが分かれているので起こらないし。
新しい品番のPICではLATxという出力専用レジスタがあるのでやっぱり起こらない。

結局これに5時間くらい悩まされて頭が痛くなった。
やっぱりくせがあるぜ8bitのPIC...


*おまけ

39:            void digitalWrite(int p,int x)
40:            {
41:                if(p == sda0)
0535  0870     MOVF __pcstackCOMMON, W
0536  0471     IORWF 0x71, W
0537  1D03     BTFSS STATUS, 0x2
0538  2D43     GOTO 0x543
42:                {
43:                    RB4 = x;
0539  1C72     BTFSS x, 0x0
053A  2D3F     GOTO 0x53F
053B  1283     BCF STATUS, 0x5
053C  1303     BCF STATUS, 0x6
053D  1606     BSF PORTB, 0x4
053E  0008     RETURN
053F  1283     BCF STATUS, 0x5
0540  1303     BCF STATUS, 0x6
0541  1206     BCF PORTB, 0x4
44:                }else if(p == scl0){
0542  0008     RETURN
0543  0370     DECF __pcstackCOMMON, W
0544  0471     IORWF 0x71, W
0545  1D03     BTFSS STATUS, 0x2
0546  0008     RETURN
45:                    RB5 = x;
0547  1C72     BTFSS x, 0x0
0548  2D4D     GOTO 0x54D
0549  1283     BCF STATUS, 0x5
054A  1303     BCF STATUS, 0x6
054B  1686     BSF PORTB, 0x5
054C  0008     RETURN
054D  1283     BCF STATUS, 0x5
054E  1303     BCF STATUS, 0x6
054F  1286     BCF PORTB, 0x5
46:                }
0550  0008     RETURN
47:            }

2015年3月1日日曜日

秋月のI2C-LCDを、Arduinoのライブラリを使わずにソフトウェアI2Cマスタから操作するコード

散々皆さん書かれてるでしょうが、必要とする人もいるかもと思い書いておきます。
秋月のI2C-LCDを、Arduinoのライブラリを使わずにソフトウェアI2Cマスタから操作するコード
とある装置のデバッグ用に書いたので、液晶を操作するのであればこんなものを使わずにライブラリを使ったほうがいいです。