GR-SAKURA
GR-KURUMI
GR-COTTON
GR-CITRUS
GR-PEACH
GR-KAEDE
GR-ADZUKI
GR-LYCHEE
GR-ROSE
GR-MANGO(*)
SNShield
Web Compiler
IDE for GR
TOPPERS関連
女子美コラボ
その他
※プロデューサミーティング中
作り方使い方資料
イベント関連
作品記事
体験記事
ライブラリ
ツール
その他・過去ファイル
下記のループで、1500nsecの周期になることを、オシロで確認してます。
for (;;) { digitalWrite( 0, HIGH ); digitalWrite( 0, LOW ); }
これだと、http://www.switch-science.com/catalog/1286/ フルカラーシリアルLEDテープを制御しようとすると、ちょいとたりません、データシートによると、350nsecのHIGHパルスを作る必要があるので、うまくいきません。
組み込みアセンブラでしょうか?
H: 350nsec, L:800nsecの信号と、H:700nsec, L:600nsecの信号を作る必要があります。
どなたか、ソース公開してましたっけ?
1500nsec の周期は GR-KURUMI の digitalWrite() では無理っぽい数字なので、消去法で GR-SAKURA でのことだと思いますが、まあ、digitalWrite()での制御が間に合わないことは既に判明してるみたいなので、
で、GR-SAKURA なら何とかなりそうな気はします(GR-KURUMI なら asm 使わないと無理そう)。
フォロありがとうございます。GR-SAKURAってことを書き忘れました。
ところで、「ポートへの直アクセス」はどこかにサンプルありましたっけ? なんか、「ポートへの直アクセス」を、マクロで提供してもいい感じします。
ポートへの直アクセスは『RX63Nグループ、RX631グループ ユーザーズマニュアル ハードウェア編』とGR-SAKURAのピン定義と gr_common/include/tkdnhal/iodefine_gcc63n.h 辺りを参照するのが良いと思います。
/*GR-SAKURA Sketch Template Version: V1.08*/ #include <rxduino.h> #include <iodefine_gcc63n.h> const int waitHigh = 10; const int waitLow = 10; void setup() { pinMode(0, OUTPUT); noInterrupts(); uint8_t p2podr = PORT2.PODR.BYTE; uint8_t p21high = p2podr | 0x02; uint8_t p21low = p2podr & ~0x02; for (;;) { #if 0 digitalWrite(0, HIGH); #elif 0 PORT2.PODR.BIT.B1 = 1; #elif 1 PORT2.PODR.BYTE = p21high; #endif for (int w = waitHigh; w != 0; w--) { asm volatile ("nop\n"); } #if 0 digitalWrite(0, LOW); #elif 0 PORT2.PODR.BIT.B1 = 0; #elif 1 PORT2.PODR.BYTE = p21low; #endif for (int w = waitLow; w != 0; w--) { asm volatile ("nop\n"); } } } void loop() { }
上記のコードで CPU のクロック 96MHz の 4 だか 5 クロックの精度(42n? 52nS?)でパルス幅の調整ができるみたいなので、±150nS の精度でパルス幅を合わせる用途にはまあ使えるじゃないでしょうか。
上記のコードで CPU のクロック 96MHz の 4 だか 5 クロックの精度(42n? 52nS?)
時間待ちの各命令を『ユーザーズマニュアル ハードウェア編』で実行サイクルを確認したら、
00000025 <.LBB4>: 25: 03 nop 26: 60 1e sub #1, r14 28: 21 fd bne.b 25 <.LBB4>
1+1+3=5(52nS)クロックですね。
asm 使えば 1 クロック(10nS)単位での時間待ちも書けますが、今回の用途には先の例で十分だと思います。
なぜ『RXファミリ ユーザーズマニュアル ソフトウェア編』には各命令の実行サイクル数が載っていないのだろう?
『RL78 ファミリ ユーザーズマニュアル ソフトウェア編』には RL78-S1 と RL78-S2 と RL78-S3 が別表で載っててスーパー見辛いのでその辺は良し悪しか。
でもまあ、『~ソフトウェア編』に「実行サイクル数は『~ハードウェア編』見てね」くらい書いてあってもいいと思う。
RX では「サイクル数」と書かれてるものが RL78 では「クロック数」と書かれてるのもなんだかな。同じ会社の製品なんだから用語の統一くらいやって然るべき。
for (int w = waitHigh; w != 0; w--) { asm volatile ("\n"); }
空ループって、最低限改行でも書いときゃ削除されないんだなあ、なんか命令書かんといかんと思ってたわ。
23: 66 ae mov.l #10, r14 00000025 <.LBB4>: 25: 60 1e sub #1, r14 27: 21 fe bne.b 25 <.LBB4>
ありがとうございます。さっそく、試してみます。
まず、
const int waitHigh = 6;const int waitLow = 13;で、1 codeのパターンが出ました。waitHighは、5以下になると、ノーウエイトになるようです。
次は、0 codeをやってみます。
0 codeは、
const int waitHigh = 6;const int waitLow = 13;で出ました。
あとは、これを組み合わせると、光らせることができる。
注意としては、スイッチサイエンスのフルカラーシリアルLEDテープは、2種類あって、タイミング微妙に異なってますので、それに合わせて、微調整が必要です。本件は、古い方です。
お手数かけ、ありがとうございました。
べたでありますが、フルカラーLEDリボンの制御ができてきました。サンプルソースは下記になります。
-------
/*GR-SAKURA Sketch Template Version: V1.08*/ #include <rxduino.h> #include <iodefine_gcc63n.h> const int waitHigh0 = 6; const int waitLow0 = 13; const int waitHigh1 =12; const int waitLow1 = 10; const int waitRet = 1000; uint8_t p2podr; uint8_t p21high; uint8_t p21low; void setup() { pinMode(PIN_LED0,OUTPUT); pinMode(PIN_LED1,OUTPUT); pinMode(PIN_LED2,OUTPUT); pinMode(PIN_LED3,OUTPUT); noInterrupts(); p2podr = PORT2.PODR.BYTE; p21high = p2podr | 0x02; p21low = p2podr & ~0x02; pinMode( 0 ,OUTPUT); } void code_0(void) { int i; PORT2.PODR.BIT.B1 = 1; for ( i=0; i<waitHigh0; i++ ) { asm volatile ("nop\n"); } PORT2.PODR.BIT.B1 = 0; for ( i=0; i<waitLow0; i++ ) asm volatile ("nop\n"); } void code_1(void) { int i; PORT2.PODR.BIT.B1 = 1; for ( i=0; i<waitHigh1; i++ ) { asm volatile ("nop\n"); } PORT2.PODR.BIT.B1 = 0; for ( i=0; i<waitLow1; i++ ) asm volatile ("nop\n"); } void code_ret(void) { int i; for ( i=0; i<waitRet; i++ ) asm volatile ("nop\n"); } void loop() { int i; code_ret(); for(;;) { // 1つ目 // Green code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); // Red code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); // Blue code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); // 2つ目 // Green code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); // Red code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); // Blue code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_ret(); interrupts(); delay(1000); noInterrupts(); // Green code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); // Red code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); // Blue code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); // // Green code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); // Red code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); code_0(); // Blue code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); code_1(); code_ret(); interrupts(); delay(1000); noInterrupts(); } }
べたべたですけど、ご参考。
配線は、5V電源は、USBコネクタのところにあるスルーホールからとってます。フルカラーLEDリボンのDI端子は、GR-SAKURAのピン0番と直結してます。
お、いい感じですね。
ありがとうございました。もう少し、サンプルソースコードをエンハンスしました。ここまで作っとけば、いろいろ使えますね。動作の様子は、youtubeにアップしてます。
タイマー割り込みの10msec間隔で、バッファの情報を表示します。このサンプルでは色相を移動させるように表示してます。あと、リボンの長さは、256個までで、それ以下なら、下記のソースコードを修正せずに、動作します。
/*GR-SAKURA Sketch Template Version: V1.08*/ #include <rxduino.h> #include <iodefine_gcc63n.h> const int waitHigh0 = 6; const int waitLow0 = 13; const int waitHigh1 =12; const int waitLow1 = 10; const int waitRet = 1000; void code_0(void); void code_1(void); void code_ret(void); void intrTimer(void); uint8_t p2podr; uint8_t p21high; uint8_t p21low; unsigned char r[256]; unsigned char g[256]; unsigned char b[256]; unsigned char ptr = 0; unsigned int timerCnt = 0; unsigned int loopCnt = 0; void setup() { int i; pinMode(PIN_LED0,OUTPUT); pinMode(PIN_LED1,OUTPUT); pinMode(PIN_LED2,OUTPUT); pinMode(PIN_LED3,OUTPUT); p2podr = PORT2.PODR.BYTE; p21high = p2podr | 0x02; p21low = p2podr & ~0x02; for( i=0; i<256; i++ ) { r[i] = 0x00; g[i] = 0x00; b[i] = 0x00; } pinMode( 0 ,OUTPUT); code_ret(); timer_regist_userfunc(intrTimer); } void code_0(void) { int i; PORT2.PODR.BIT.B1 = 1; for ( i=0; i<waitHigh0; i++ ) { asm volatile ("nop\n"); } PORT2.PODR.BIT.B1 = 0; for ( i=0; i<waitLow0; i++ ) asm volatile ("nop\n"); } void code_1(void) { int i; PORT2.PODR.BIT.B1 = 1; for ( i=0; i<waitHigh1; i++ ) { asm volatile ("nop\n"); } PORT2.PODR.BIT.B1 = 0; for ( i=0; i<waitLow1; i++ ) asm volatile ("nop\n"); } void code_ret(void) { int i; for ( i=0; i<waitRet; i++ ) asm volatile ("nop\n"); } void intrTimer(void) { int i; unsigned char cur; if ( ((timerCnt++) % 10) != 0 ) return; for( i=0, cur=(ptr - 1); i<256; i++, cur-- ) { // Green if (g[cur] & 0x80) code_1(); else code_0(); if (g[cur] & 0x40) code_1(); else code_0(); if (g[cur] & 0x20) code_1(); else code_0(); if (g[cur] & 0x20) code_1(); else code_0(); if (g[cur] & 0x08) code_1(); else code_0(); if (g[cur] & 0x04) code_1(); else code_0(); if (g[cur] & 0x02) code_1(); else code_0(); if (g[cur] & 0x01) code_1(); else code_0(); // Red if (r[cur] & 0x80) code_1(); else code_0(); if (r[cur] & 0x40) code_1(); else code_0(); if (r[cur] & 0x20) code_1(); else code_0(); if (r[cur] & 0x10) code_1(); else code_0(); if (r[cur] & 0x08) code_1(); else code_0(); if (r[cur] & 0x04) code_1(); else code_0(); if (r[cur] & 0x02) code_1(); else code_0(); if (r[cur] & 0x01) code_1(); else code_0(); // Blue if (b[cur] & 0x80) code_1(); else code_0(); if (b[cur] & 0x40) code_1(); else code_0(); if (b[cur] & 0x20) code_1(); else code_0(); if (b[cur] & 0x10) code_1(); else code_0(); if (b[cur] & 0x08) code_1(); else code_0(); if (b[cur] & 0x04) code_1(); else code_0(); if (b[cur] & 0x02) code_1(); else code_0(); if (b[cur] & 0x01) code_1(); else code_0(); } code_ret(); } void color_phase( unsigned char *r, unsigned char *g, unsigned char *b, unsigned int phase ) // 12bit { unsigned int theta = phase & 0xfff; unsigned int offset = theta % 683; switch ( theta / 683 ) { case 0: *r = 0xff; *g = (offset * 255)/ 683; *b = 0x00; break; case 1: *r = ((683 - offset) * 255)/ 683; *g = 0xff; *b = 0x00; break; case 2: *r = 0x00; *g = 0xff; *b = (offset * 255)/ 683; break; case 3: *r = 0x00; *g = ((683 - offset) * 255)/ 683; *b = 0xff; break; case 4: *r = (offset * 255)/ 683; *g = 0x00; *b = 0xff; break; case 5: default: *r = 0xff; *g = 0x00; *b = ((683 - offset) * 255)/ 683; } } void loop() { color_phase( &(r[ptr]), &(g[ptr]), &(b[ptr]), loopCnt ); ptr++; loopCnt += 10; delay(100); }
さて、これを、γ線分光計に接続せんと、、、
とりあえず、応用例として、γ線検出パルスのとりっぱくれが発生すると思うのですが、γ線分光計の検出パルスの電圧を、色相へマッピングして、フルカラーLEDリボンで光らせてみました。何か、演出的なパターンを加えないと、地味でした(^^ゞ
まだ、ゴミコードトバグが混じってイますが、以下に、サンプルソースを置いておきます。
/*GR-SAKURA Sketch Template Version: V1.08*/ // GSR_2014_02 // (C) 2014, DIGI-P, BSD LICENSE for AS-IS. // #include <rxduino.h> #include <iodefine_gcc63n.h> #define INTERVAL 100 unsigned long loopCnt = 0; #define SIZE_OF_CNT (0x1000) unsigned long cnt[ SIZE_OF_CNT ]; unsigned short vPuls_curr = 0; unsigned short vPuls_prv1 = 0; unsigned short vPuls_prv2 = 0; unsigned short vPuls_mark = 0; long onLED0 = 0; long onLED1 = 0; long onLED2 = 0; long onLED3 = 0; void intrTimer(void); const int waitHigh0 = 6; const int waitLow0 = 13; const int waitHigh1 =12; const int waitLow1 = 10; const int waitRet = 1000; void code_0(void); void code_1(void); void code_ret(void); void paint(void); void color_phase( unsigned char *r, unsigned char *g, unsigned char *b, unsigned int phase ); uint8_t p2podr; uint8_t p21high; uint8_t p21low; unsigned char r[256]; unsigned char g[256]; unsigned char b[256]; unsigned char ptr = 0; unsigned int timerCnt = 0; void setup() { int i; pinMode(PIN_LED0,OUTPUT); pinMode(PIN_LED1,OUTPUT); pinMode(PIN_LED2,OUTPUT); pinMode(PIN_LED3,OUTPUT); digitalWrite(PIN_LED0,0); digitalWrite(PIN_LED1,0); digitalWrite(PIN_LED2,0); digitalWrite(PIN_LED3,0); pinMode( A0, INPUT ); for ( i=0; i<SIZE_OF_CNT; i++ ) { cnt[i] = 0; } loopCnt = 0; p2podr = PORT2.PODR.BYTE; p21high = p2podr | 0x02; p21low = p2podr & ~0x02; for( i=0; i<256; i++ ) { r[i] = 0x00; g[i] = 0x00; b[i] = 0x00; } pinMode( 0 ,OUTPUT); code_ret(); // Serial.begin(38400, SCI_USB0 ); analogReference(RAW12BIT); // timer_regist_userfunc( intrTimer ); } void intrTimer(void) { vPuls_curr = analogRead( A0 ); if ((vPuls_prv1 > vPuls_prv2) && (vPuls_curr <= vPuls_prv1)) { vPuls_mark = vPuls_prv1; if ( cnt[vPuls_prv1] != 0xffffffff ) { cnt[vPuls_prv1]++; } if (vPuls_prv1 > 200) { onLED0 = 50; } if (vPuls_prv1 >= 1024) { onLED1 = 200; } if (vPuls_prv1 >= 2048) { onLED2 = 300; } if (vPuls_prv1 >= 3072) { onLED3 = 400; } } vPuls_prv2 = vPuls_prv1; vPuls_prv1 = vPuls_curr; loopCnt++; } void loop() { int i; for( i=0; i<10000; i++ ) { intrTimer(); onLED0--; if (onLED0 < 0) { onLED0 = 0; digitalWrite( PIN_LED0, 0 ); } else { digitalWrite( PIN_LED0, 1 ); } onLED1--; if (onLED1 < 0) { onLED1 = 0; digitalWrite( PIN_LED1, 0 ); } else { digitalWrite( PIN_LED1, 1 ); } onLED2--; if (onLED2 < 0) { onLED2 = 0; digitalWrite( PIN_LED2, 0 ); } else { digitalWrite( PIN_LED2, 1 ); } onLED3--; if (onLED3 < 0) { onLED3 = 0; digitalWrite( PIN_LED3, 0 ); } else { digitalWrite( PIN_LED3, 1 ); } if ( vPuls_mark > 0 ) { if (vPuls_mark > 50) { color_phase( &(r[ptr]), &(g[ptr]), &(b[ptr]), vPuls_mark ); ptr++; } vPuls_mark = 0; paint(); } } } void code_0(void) { int i; PORT2.PODR.BIT.B1 = 1; for ( i=0; i<waitHigh0; i++ ) { asm volatile ("nop\n"); } PORT2.PODR.BIT.B1 = 0; for ( i=0; i<waitLow0; i++ ) asm volatile ("nop\n"); } void code_1(void) { int i; PORT2.PODR.BIT.B1 = 1; for ( i=0; i<waitHigh1; i++ ) { asm volatile ("nop\n"); } PORT2.PODR.BIT.B1 = 0; for ( i=0; i<waitLow1; i++ ) asm volatile ("nop\n"); } void code_ret(void) { int i; for ( i=0; i<waitRet; i++ ) asm volatile ("nop\n"); } void paint(void) { int i; unsigned char cur; noInterrupts(); for( i=0, cur=(ptr - 1); i<256; i++, cur-- ) { // Green if (g[cur] & 0x80) code_1(); else code_0(); if (g[cur] & 0x40) code_1(); else code_0(); if (g[cur] & 0x20) code_1(); else code_0(); if (g[cur] & 0x20) code_1(); else code_0(); if (g[cur] & 0x08) code_1(); else code_0(); if (g[cur] & 0x04) code_1(); else code_0(); if (g[cur] & 0x02) code_1(); else code_0(); if (g[cur] & 0x01) code_1(); else code_0(); // Red if (r[cur] & 0x80) code_1(); else code_0(); if (r[cur] & 0x40) code_1(); else code_0(); if (r[cur] & 0x20) code_1(); else code_0(); if (r[cur] & 0x10) code_1(); else code_0(); if (r[cur] & 0x08) code_1(); else code_0(); if (r[cur] & 0x04) code_1(); else code_0(); if (r[cur] & 0x02) code_1(); else code_0(); if (r[cur] & 0x01) code_1(); else code_0(); // Blue if (b[cur] & 0x80) code_1(); else code_0(); if (b[cur] & 0x40) code_1(); else code_0(); if (b[cur] & 0x20) code_1(); else code_0(); if (b[cur] & 0x10) code_1(); else code_0(); if (b[cur] & 0x08) code_1(); else code_0(); if (b[cur] & 0x04) code_1(); else code_0(); if (b[cur] & 0x02) code_1(); else code_0(); if (b[cur] & 0x01) code_1(); else code_0(); } code_ret(); interrupts(); } void color_phase( unsigned char *r, unsigned char *g, unsigned char *b, unsigned int phase ) // 12bit { unsigned int theta = phase & 0xfff; unsigned int offset = theta % 683; switch ( theta / 683 ) { case 0: *r = 0xff; *g = (offset * 255)/ 683; *b = 0x00; break; case 1: *r = ((683 - offset) * 255)/ 683; *g = 0xff; *b = 0x00; break; case 2: *r = 0x00; *g = 0xff; *b = (offset * 255)/ 683; break; case 3: *r = 0x00; *g = ((683 - offset) * 255)/ 683; *b = 0xff; break; case 4: *r = (offset * 255)/ 683; *g = 0x00; *b = 0xff; break; case 5: default: *r = 0xff; *g = 0x00; *b = ((683 - offset) * 255)/ 683; } }
高エネルギーなパルス、青色が出た〜
今、DC5VのACアダプタにすると、LED全体がノイジーにちかちかする現象に出くわしてます。制御信号が、ACアダプタの出力電圧が、5.XVと高くなったときに、GR-SAKURAの3.3V出力が、Highに認識されなくなる状態っておきますかね。トランジスタ1つかました方が良いのかどうか不明。
(^_^;)
製品のページ見ると
と結構大食いな様ですが、ACアダプタの容量に余裕はありますか?
レス、ありがとうございます。だめでした。2AのACアダプタでした(^^ゞ 4A以上で、買って試してみます。
今、容量の大きなACアダプタへ変えて試したところ、まったくLEDが光らなくなりました。リボンの電源電圧を、ダイオード1つ分下げると、正常に光るようになりました。結局、リボンの電源は、4.7V-4.8Vあたりにしないと、GR-SAKLURAの3.3Vは、Hレベルに認識されないということみたいです。GR-SAKURAのオンボードでレベル変換回路を搭載して、何本か、5V出力のピンがあると便利ですね。
ノウハウが蓄積されていく感じでいいですね。
「GR-SAKURA シリアルLED」でぐぐったら、carcon999 さんもシリアルLEDやられてました。
blogs.yahoo.co.jp/.../36988734.html
blogs.yahoo.co.jp/.../37013871.html
つか、Rulzで検索したら↓の投稿あった。
japan.renesasrulz.com/.../led.aspx
# なんかコメント付けてる人とかいるし
有難うございます。これでわかったことは、リボンの電源電圧を3.7Vで、使ってるってことです。やはり、5V電源で使うと、うまくいかないという仮説の裏付け。
あと、そう言えば、カチューシャで、KazuyukiEguchi さんも使ってましたね。
GR-KURUMIにFTDI 5Vにして使ってます。実は3.3Vだと24個光らなかったんです。
スイッチサイエンスの1mLEDテープを最近購入したので、近いうちに試してみます。
今のところ秋月で売ってる5V4AのACアダプタに、秋月で売ってる400V5Aの整流ダイオード(http://akizukidenshi.com/download/er500_series.pdf )を直列に入れたものを電源として、LEDテープは正常動作してます。
皆様、有り難うございました。
ケースの加工が完了して、今、外観も無事、完成しました。γ線分光計床置タイプ・インテリア風です。
モジュールは、使い回せるように、BNCケーブルで接続するように、アルミダイキャストケースで、セパレートタイプにしました。皆様のご家庭に、1台飾られては、どうでしょうか?
動きのテンポは、遅いです。
最初のサンプルに戻りますが、少々改造した動作の様子です。