marua が 2021年02月11日10時33分54秒 に編集
21/02/11 データの作り方追記
記事種類の変更
製作品
本文の変更
![キャプションを入力できます](https://camo.elchika.com/6af257a5db5073c649de75c87f0961494a11645b/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33633934613036612d653465342d343838392d383133342d3434636466393330333066352f36313537303934332d633138382d346532312d616564662d336631653264353531613237/) ![キャプションを入力できます](https://camo.elchika.com/537903503fefb8839f9aa13c71363a34e8c5b0df/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33633934613036612d653465342d343838392d383133342d3434636466393330333066352f32333561386132322d313839392d346233392d616235342d396664306666353064306164/) 基板を振って LEDでメッセージを描く「LEDスティック」です。 市販のボードのCPU部分にATmega328を載せて、Arduino IDEでプログラムを作成。 単3電池2本で動かすため、内臓の8MHzオシレータをクロック源にしています。 ![キャプションを入力できます](https://camo.elchika.com/fdfdf7808155ee550b0022877c07ece8294fe083/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33633934613036612d653465342d343838392d383133342d3434636466393330333066352f61616131343531322d663362342d343037622d383430362d353636643031353231363865/) 最終的には、市販のLEDペンライトのケースに入れました。 ボタン操作で、8種類のメッセージを選択することが出来ます。 プログラム自身は 一定時間毎に表示を切り替える簡単な処理なので、全文字が表示できるよう 振るスピードを調整する必要が有ります。 (^_^; ![キャプションを入力できます](https://camo.elchika.com/9ee6f7733b29ebf2a4cc0e9476430d476e161209/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33633934613036612d653465342d343838392d383133342d3434636466393330333066352f33633264303138362d623865362d346136342d383464662d653438363336623361336330/) ```arduino:メインプログラム (16LED.ino) #include "16LED_text.h" int LED1 = 19; // PC5(A5) "L" is lit int LED2 = 18; // PC4(A4) int LED3 = 17; // PC3(A3) int LED4 = 16; // PC2(A2) int LED5 = 15; // PC1(A1) int LED6 = 14; // PC0(A0) int LED7 = 13; // PB5 int LED8 = 12; // PB4 int LED9 = 11; // PB3 int LED10 = 10; // PB2 int LED11 = 9; // PB1 int LED12 = 8; // PB0 int LED13 = 7; // PD7 int LED14 = 6; // PD6 int LED15 = 5; // PD5 int LED16 = 4; // PD4 int S3 = 3; // PD3: Select-SW int S2 = 2; // PD2: Start-SW // PD1: TxD // PD0: RxD int sel_SW = 0x08; // PD3 int stt_SW = 0x04; // PD2 int dMask7 = 0x07; // (0000 0xxx) int dMask15 = 0x0F; // (0000 xxxx) int ver = 1; // ver 0.01 int mode = 0; int item_num = 0; // item No. int line; int dbg_count = 0; int task = 0; unsigned long tim0; unsigned int dLED; int blink_task = 0; unsigned long blink_tim0; int tMessage[] = {&mes0, &mes1, &mes2, &mes3, &mes4, &mes5, &mes6, &mes7}; int lMessage[] = {sizeof(mes0)/2,sizeof(mes1)/2,sizeof(mes2)/2,sizeof(mes3)/2,sizeof(mes4)/2,sizeof(mes5)/2,sizeof(mes6)/2,sizeof(mes7)/2}; // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. //pinMode(LED_BUILTIN, OUTPUT); pinMode(LED1, OUTPUT); digitalWrite(LED1, HIGH); pinMode(LED2, OUTPUT); digitalWrite(LED2, HIGH); pinMode(LED3, OUTPUT); digitalWrite(LED3, HIGH); pinMode(LED4, OUTPUT); digitalWrite(LED4, HIGH); pinMode(LED5, OUTPUT); digitalWrite(LED5, HIGH); pinMode(LED6, OUTPUT); digitalWrite(LED6, HIGH); pinMode(LED7, OUTPUT); digitalWrite(LED7, HIGH); pinMode(LED8, OUTPUT); digitalWrite(LED8, HIGH); pinMode(LED9, OUTPUT); digitalWrite(LED9, HIGH); pinMode(LED10, OUTPUT); digitalWrite(LED10, HIGH); pinMode(LED11, OUTPUT); digitalWrite(LED11, HIGH); pinMode(LED12, OUTPUT); digitalWrite(LED12, HIGH); pinMode(LED13, OUTPUT); digitalWrite(LED13, HIGH); pinMode(LED14, OUTPUT); digitalWrite(LED14, HIGH); pinMode(LED15, OUTPUT); digitalWrite(LED15, HIGH); pinMode(LED16, OUTPUT); digitalWrite(LED16, HIGH); pinMode(S3, INPUT); pinMode(S2, INPUT); Serial.begin(9600); Serial.println("16LED v0.05"); if (~PIND & sel_SW) {mode =100;} // selSW ON => goto Test0 } // the loop function runs over and over again forever void loop() { switch (mode) { case 0: selItem(); // Item select break; case 1: showMess(tMessage[item_num], lMessage[item_num]); // //test0(); break; case 100: chkSelOFF(); // Select SW OFF check break; case 101: test0(); // LED1 to 16 ON/OFF break; case 102: test1(); // Switch Check break; default: mode = 0; break; } } // // ***** Test Mode ***** // void test0(void) // LED No.16 to 1 ON/OFF // void test1(void) // Switch Check // // ***** Normal Mode ***** // void selItem(void) // Select Item // void showMess(int *mes, int len) // show Message void showMess(int *mes, int len) { switch (task) { case 0: line = 0; task++; tim0 = micros(); Serial.print("Start "); Serial.print(item_num); Serial.println(); break; case 1: if ((micros() - tim0) > 200000) {task++; } break; case 2: //setLED(mes0[line]); setLED(mes[line]); tim0 = micros(); task++; break; case 3: if ((micros() - tim0) > 3000) { //if (line < sizeof(mes0)-1) { if (line < len-1) { line++; task--; } else { task++; tim0 = micros(); setLED(0); } } break; case 4: if ((micros() - tim0) > 200000) {task++; } break; default: task = 0; mode =0; // Serial.println("End"); break; } } // ***** Mode = 0 ***** void selItem(void) { // Select Item chkSelSW(); // item select blinkItem(); // item No. Blinking chkSttSW(); // Start SW check } void blinkItem(void) { unsigned int l; switch (blink_task) { case 0: l = 0x8000; for (int i=0; i<item_num; i++) { l = l >> 1; } setLED(l); // LED ON blink_tim0 = micros(); blink_task++; break; case 1: dbg_count++; if ((micros() - blink_tim0) > 50000){ setLED(0); // LED OFF blink_tim0 = micros(); blink_task++; } break; case 2: if ((micros() - blink_tim0) > 900000){ blink_task++; } break; default: //Serial.println(dbg_count); //delay(10); blink_task = 0; break; } } void chkSttSW(void) { // Start SW check if (~PIND & stt_SW) { mode = 1; task = 0; //Serial.println("Start"); } } void chkSelSW(void) { // item select switch (task) { case 0: // SW ON check if (~PIND & sel_SW) { item_num = (item_num + 1) & dMask7; Serial.print("SW ON , Item = "); Serial.print(item_num); task++; } break; case 1: // SW OFF check if (PIND & sel_SW) { tim0 = micros(); task++; } break; case 2: // wait if ((micros() - tim0) > 300000){ task++; } break; default: task = 0; break; } } void test1(void) { // Switch Check switch (task) { case 0: // LED ON //Serial.println(PIND, HEX); if ((~PIND & (sel_SW | stt_SW)) != 0x00) { Serial.println((PIND & (sel_SW | stt_SW)), BIN); // (xxxx xx00) setLED(~PIND & (sel_SW | stt_SW)); // LED ON tim0 = micros(); task++; } break; case 1: // wait & LED OFF if ((micros() - tim0) > 300000){ setLED(0); // LED OFF task++; } break; default: task = 0; break; } } void test0(void) { blinkTest(); // LED16 to 1 ON/OFF chk_T0_SW(); // Select SW check } void chk_T0_SW(void) { // Select SW check if (~PIND & sel_SW) { Serial.println("goto Test1"); mode = 102; } } void blinkTest(void) { // LED16 to 1 ON/OFF switch (task) { case 0: // LED ON if (dLED == 0) {dLED = 0x8000;} setLED(dLED); // LED ON dLED = dLED >> 1; tim0 = micros(); task++; break; case 1: // wait & LED OFF if ((micros() - tim0) > 100000){ setLED(0); // LED OFF tim0 = micros(); task++; } break; case 2: // wait if ((micros() - tim0) > 400000){ task ++; } break; default: task = 0; break; } } void chkSelOFF(void) { // Select SW OFF check if (PIND & sel_SW) { Serial.println("goto Test0"); mode = 101; } } void setLED(unsigned int data) { unsigned int p,d; p = PORTC & 0xc0; // (xx00 0000) d = ~(data >> 10); // (00cc cccc) bb bbbb dddd PORTC = p | (d & 0x3F); // (00cc cccc) p = PORTB & 0xc0; // (xx00 0000) d = ~(data >> 4); // (00bb bbbb) dddd PORTB = p | (d & 0x3F); // (00bb bbbb) p = PORTD & 0x0f; // (0000 xxxx) d = ~(data << 4); // bbbb (dddd 0000) PORTD = p | (d & 0xf0) ; // (dddd 0000) } ``` ```arduino:表示データ(16LED_text.h) unsigned int mes0[] = { 0, 0, 0, 0, 4104, 8184, 8184, 4104, 0, 0, 0, 960, 2016, 2032, 1016, 2032, 2016, 960, 0, 0, 0, 512, 6720, 1600, 1472, 1208, 128, 0, 0, 320, 224, 152, 192, 0, 0, 512, 520, 264, 16, 96, 384, 3584, 0, 0, 2056, 2056, 2064, 2080, 2240,20224,40960, 16384, 0 }; unsigned int mes1[] = { 0, 0, 0, 0, 2176,18560,16368, 2184, 2180, 4356, 260, 8, 48, 0, 0, 0, 4, 1048, 1056, 17472,10400, 2336, 3608, 2052, 4, 4, 0, 0, 0, 0, 4224, 4352, 4872, 5396, 5396, 6420, 4232, 112, 0, 0, 0, 0, 128, 128, 256, 256, 256, 128, 128, 64, 64, 128, 256, 0, 0 }; unsigned int mes2[] = { 0, 0, 0, 0, 2072, 2340, 2340,10532, 8184, 2336, 4640, 4112, 12, 0, 0, 0, 512, 1024, 1136, 3976, 2052, 4, 8, 112, 896, 7168, 2048, 1024, 512, 0, 0, 0, 8304, 8072, 260, 260, 516, 516, 1032, 0, 0, 0, 64, 128, 128, 128, 128, 64, 64, 64, 128 }; unsigned int mes3[] = { 0, 0, 0, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855 }; unsigned int mes4[] = { 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855 }; unsigned int mes5[] = { 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855 }; unsigned int mes6[] = { 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855 }; unsigned int mes7[] = { 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855, 61680,61680,61680,61680, 3855, 3855, 3855, 3855 }; ```
【おまけ】 表示データの作り方 1、表計算ソフトで 「縦16×横64」程度のマス目を作る。 2、LEDを光らせたいマス目に"1"を書き込む。 ![表示データの例](https://camo.elchika.com/762486a80d78166fb28d97f908f3ec7a4949e6c9/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33633934613036612d653465342d343838392d383133342d3434636466393330333066352f33336434373735612d656634302d346233382d623263382d313938303837366533616532/) 3、各列毎に、一番上のマス目を「2^15」~ 一番下のマス目を「2^0」に重みづけして 「各マス目の値」を掛けた結果の「和」を計算する。 ![重みづけをして計算](https://camo.elchika.com/77481ba503feb64ef0f8a01db86d9e1707998578/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33633934613036612d653465342d343838392d383133342d3434636466393330333066352f32383862383936352d373766622d343735382d383234352d623030386430363234353431/) 4、表示する範囲の 重みづけの和を 選択・コピーし、新しいファイルに貼り付ける。 5、新しく作ったファイルをCSV形式で保存する。 6、エディタでCSVファイルを開き データをソースに貼り付ける。 ![CSVファイルの中身](https://camo.elchika.com/604299d9e231812b565864a6a6d0a769771132f0/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33633934613036612d653465342d343838392d383133342d3434636466393330333066352f36303235623734352d306664642d343038352d396663372d646234633063346535666366/)