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関連
女子美コラボ
その他
※プロデューサミーティング中
作り方使い方資料
イベント関連
作品記事
体験記事
ライブラリ
ツール
その他・過去ファイル
がじぇっとるねさすゆーざー会の皆様、はじめまして。
ゆーざー会の皆様のプログラムの記述を見ると素晴らしく、なるほど玄人であると感じております。
私はこのようなボードのプログラムは初めてでして、なかなか難しい部分もありますが、まずはSAKURAで遊ばせて頂いております。
SAKURAやKURUMIが目指しているところは【より多くの方に楽しんでもらう】であろうかと思いましたが、私のような初心者にはなかなか難しい部分も多く、これからのさらなる普及に対しては、プログラムパーツを増やす事が大切ではないかと感じております。
さて、そのような意味もあり、今般私が取り組んだのは、デジタルスイッチの扱いでして、割り込みが用意されていないスイッチに対しても動作可能とするように、かつ、汎用化する事でした。
現状でとりあえず使用できるものと思いますが、まだ長押しを有効にした場合に操作スイッチがカウントされる問題があり、不完全です。よって、是非皆様に解決のご指導を頂ければと思っております。
とりあえず参考までに掲載いたします。
既に類似のプログラムがあるものと思いますが探しきれていません。(・・;)
どうぞよろしくお願いいたします。
/*
* ToggleSwitch.h
* Created on: 2013/10/10
* Author: hiro
* 使い方
* ToggleSwitch.h 及び ToggleSwitch.cpp は[gr_common]の[lib]フォルダにインポートする。
* コンストラクタには使用するスイッチの値を渡す。 例: ToggleSwitch sw(PIN_SW)
* 長押しボタンを使用する場合は、有効化する時間をコンストラクタの第二引数に渡す(ミリ秒)。 例: ToggleSwitch sw(PIN_SW,1000)
* get_interval, set_interval は長押し有効化時間の取得・設定関数
* ボタンをチェックするため、update関数を周期関数等により呼び出す
* 押された回数をcount()で取得する。
* increment()は押された回数を強制的にインクリメント(+1)するもの
*/
#include <rxduino.h>
#ifndef TOGGLESWITCH_H_
#define TOGGLESWITCH_H_
class ToggleSwitch {
private:
unsigned long m_start; // 長押しスイッチのON時刻の保持
unsigned long m_interval; // 長押しスイッチのON認識の時間間隔
int m_count; // スイッチのカウント数
int m_switch_no; // スイッチ番号の保持
boolean m_prev_condition; // 前回の状態の保持用
boolean m_curr_condition; // 今回の状態
public:
/* コンストラクタ 長押しボタン不使用。 */
ToggleSwitch(int sw_no) : m_start(0), m_interval(0), m_count(0), m_switch_no(sw_no),
m_prev_condition(false),m_curr_condition(false) {}
/* コンストラクタ 長押しボタン使用。 */
ToggleSwitch(int sw_no, unsigned long interval) : m_start(0), m_interval(interval), m_count(0), m_switch_no(sw_no),
~ToggleSwitch(){} /* デストラクタ */
unsigned long get_interval(); // 長押し間隔を返す関数
void set_interval(unsigned long interval); // 長押し間隔をセットする関数
int count(); // ボタンの押された回数を返す関数
void update(); // 更新
void increment(); // 強制インクリメント
};
#endif /* TOGGLESWITCH_H_ */
* ToggleSwitch.cpp
#include "ToggleSwitch.h"
unsigned long ToggleSwitch::get_interval(){
return m_interval;
}
void ToggleSwitch::set_interval(unsigned long interval){
m_interval = interval;
int ToggleSwitch::count(){
return m_count;
void ToggleSwitch::update() {
m_prev_condition = m_curr_condition;
//ボタンOnでdigitalRead==0
m_curr_condition = digitalRead(m_switch_no)==0 ? true : false;
//On→Offでカウント値をインクリメント
if(m_prev_condition && !m_curr_condition) {
if(m_interval == 0){
++m_count;
}else{
if(m_start!=0 && (millis()-m_start) >= m_interval) ++m_count;
m_start = 0;
//Off→OnでOn時間保持
if(!m_prev_condition && m_curr_condition) m_start = millis();
void ToggleSwitch::increment(){
/*GR-SAKURA Sketch Template Version: V1.07*/
const int USE_LED = 4;
const unsigned long WAIT_TIME = 10000;
ToggleSwitch lsw(PIN_SW,1000); //長押し用のインスタンス
ToggleSwitch sw(PIN_SW); //実際の操作用のインスタンス(長押しと同じボタンを使用)
int PIN_NO[USE_LED];
boolean Sw_On = false;
int prev_count = 0;
unsigned long change_time = 0;
void timer_interrupt()
{
lsw.update();
if(lsw.count() % 2 == 0) {
change_time = 0;
return;
//WAIT_TIMEを超過した場合にlswをOff(強制インクリメント)にする。
if(change_time != 0 && (millis()-change_time) > WAIT_TIME) {
lsw.increment();
sw.update();
if(prev_count != sw.count()) change_time = millis();
prev_count =sw.count();
void setup()
PIN_NO[0] = PIN_LED0;
PIN_NO[1] = PIN_LED1;
PIN_NO[2] = PIN_LED2;
PIN_NO[3] = PIN_LED3;
/* ピン設定 */
for(int i=0; i<USE_LED; ++i){
pinMode(PIN_NO[i],OUTPUT);
pinMode(PIN_SW,INPUT);
/* タイマ設定 */
timer_init();
timer_regist_userfunc(timer_interrupt);
delay(100);
void loop() {
//sw.count()で押された回数を取得できるので、剰余を算出する事により動作を制御できる。
int tmp_cnt = sw.count() % (USE_LED + 1);
if(i<tmp_cnt) digitalWrite(PIN_NO[i],1);
else digitalWrite(PIN_NO[i],0);
それで、これで何をやりたいかといいますと、KURUMIを使って夜間のジョギング用のライトを作りたいのです。現状でテストはSAKURAを使っていますが、、。
市販品は電源が水銀電池でエコじゃなく、光り方も点灯と点滅くらいで面白くありません。
電池にすると重くなるのを嫌うでしょうから、本体部分はバッグやウエストポーチに入れてコードで繋げばいいかなっていう発想です。
必要な事は、スイッチ1個で動作モードを切り替えられる事。もちろん、スイッチに触って簡単に動作モードが変わると困るので、ボタンの長押しで設定モードに移行し、ボタンを適宜押してモードを切り替え後、長押し又は一定の時間スイッチ操作が無ければロック。
最終的には、本体と電池は密封容器に入れ、コードを引き出して、
1.電源スイッチ 2.設定スイッチ 3.LED を搭載したライト部分を作成し、このライト部分と接続、電源はできれば単4電池1本で、エネループなどを使いたい。
本件は、「2」の設定スイッチのフレームワークです。
これが出来てしまえば、ライト点滅の数種類の関数を作成してloop内で切り替えるだけと考えているのですが、、。
コードは上記の関係から5~6本必要となるので、LAN用の平たいケーブルあたり(廃品利用)が使えないかと・・・。
なお、本体の密閉容器は必須です。ジョギングの関係で汗だらけになるからです。何かいい容器が見つかればよいのですが、、。
長押しの処理ではありませんが、誤操作防止としてスイッチにフタをしてしまうのは如何でしょうか。
例えばフリスクのケースの様にスライドするタイプのケースにスイッチを収めてしまえば、誤操作は滅多に起きないと思われます。
アドバイス、ありがとうございます。フリスクのケースですか。なるほど。思いもしませんでした。
やたらと実装するより物理的に解決するのは確実ですね。ご教示ありがとうございます。
プログラムの問題点は何となく見えてきたので、折角ですから実装してみる事とします。
まずはお礼まで。
長押しにより設定をコントロールできるボタンできました。
しょうもないプログラムですみません。m(__)m
前のプログラムで、放置してロックがかかる場合は問題なく、長押しでロックをかけると問題がある事が解決のヒントでした。
ロック時のボタンの変動を食っていたので、状態をflashできるようにして解決。
/** ToggleSwitch.h* Created on: 2013/10/10* Author: hiro* 使い方* ToggleSwitch.h 及び ToggleSwitch.cpp は[gr_common]の[lib]フォルダにインポートする。* コンストラクタには使用するスイッチの値を渡す。 例: ToggleSwitch sw(PIN_SW) * 長押しボタンを使用する場合は、有効化する時間をコンストラクタの第二引数に渡す(ミリ秒)。 例: ToggleSwitch sw(PIN_SW,1000)* get_interval, set_interval は長押し有効化時間の取得・設定関数* ボタンをチェックするため、update関数を周期関数等により呼び出す* 押された回数をcount()で取得する。* increment()は押された回数を強制的にインクリメント(+1)するもの*/#include <rxduino.h> #ifndef TOGGLESWITCH_H_#define TOGGLESWITCH_H_class ToggleSwitch {private: unsigned long m_start; // 長押しスイッチのON時刻の保持 unsigned long m_interval; // 長押しスイッチのON認識の時間間隔 int m_count; // スイッチのカウント数 int m_switch_no; // スイッチ番号の保持 boolean m_prev_condition; // 前回の状態の保持用 boolean m_curr_condition; // 今回の状態public: /* コンストラクタ 長押しボタン不使用。 */ ToggleSwitch(int sw_no) : m_start(0), m_interval(0), m_count(0), m_switch_no(sw_no), m_prev_condition(false),m_curr_condition(false) {} /* コンストラクタ 長押しボタン使用。 */ ToggleSwitch(int sw_no, unsigned long interval) : m_start(0), m_interval(interval), m_count(0), m_switch_no(sw_no), m_prev_condition(false),m_curr_condition(false) {} ~ToggleSwitch(){} /* デストラクタ */ unsigned long get_interval(); /* 長押し間隔を返す関数 */ void set_interval(unsigned long interval); /* 長押し間隔をセットする関数 */ int count(); /* ボタンの押された回数を返す関数 */ void update(); /* 更新 */ void increment(); /* 強制インクリメント */ void flash(); /* m_prev_condition と m_curr_condition値をfalseにする。 */}; #endif /* TOGGLESWITCH_H_ */
/** ToggleSwitch.cpp* Created on: 2013/10/10* Author: hiro*/#include <rxduino.h> #include "ToggleSwitch.h"unsigned long ToggleSwitch::get_interval(){ return m_interval;}void ToggleSwitch::set_interval(unsigned long interval){ m_interval = interval;}int ToggleSwitch::count(){ return m_count;}void ToggleSwitch::flash(){ m_prev_condition = false; m_curr_condition = false;}void ToggleSwitch::update() { m_prev_condition = m_curr_condition; //ボタンOnでdigitalRead==0 m_curr_condition = digitalRead(m_switch_no)==0 ? true : false; //On→Offでカウント値をインクリメント if(m_prev_condition && !m_curr_condition) { if(m_interval == 0){ ++m_count; }else{ if(m_start!=0 && (millis()-m_start) >= m_interval) ++m_count; m_start = 0; } } //Off→OnでOn時間保持 if(!m_prev_condition && m_curr_condition) m_start = millis();}void ToggleSwitch::increment(){ ++m_count;}
/*GR-SAKURA Sketch Template Version: V1.07*/#include <rxduino.h>#include "ToggleSwitch.h"const int USE_LED = 4;const unsigned long WAIT_TIME = 10000;ToggleSwitch lsw(PIN_SW,1000); //長押し用のインスタンスToggleSwitch sw(PIN_SW); //実際の操作用のインスタンス(長押しと同じボタンを使用)int PIN_NO[USE_LED];boolean Sw_On = false;int prev_count = 0;unsigned long change_time = 0;void timer_interrupt(){ lsw.update(); if(lsw.count() % 2 == 0) { change_time = 0; return; }else{ if(change_time == 0) { sw.flash(); change_time = millis(); } //WAIT_TIMEを超過した場合にlswをOff(強制インクリメント)にする。 if(change_time != 0 && (millis()-change_time) > WAIT_TIME) { lsw.increment(); return; } sw.update(); if(prev_count != sw.count()) change_time = millis(); prev_count = sw.count(); }}void setup(){ PIN_NO[0] = PIN_LED0; PIN_NO[1] = PIN_LED1; PIN_NO[2] = PIN_LED2; PIN_NO[3] = PIN_LED3; /* ピン設定 */ for(int i=0; i<USE_LED; ++i){ pinMode(PIN_NO[i],OUTPUT); } pinMode(PIN_SW,INPUT); /* タイマ設定 */ timer_init(); timer_regist_userfunc(timer_interrupt); delay(100);}void loop() { //sw.count()で押された回数を取得できるので、剰余を算出する事により動作を制御できる。 int tmp_cnt = sw.count() % (USE_LED + 1); for(int i=0; i<USE_LED; ++i){ if(i<tmp_cnt) digitalWrite(PIN_NO[i],1); else digitalWrite(PIN_NO[i],0); }}
KURUMIのプログラム、仕上がりました。一応検証済みです。
割と安くできるし、エネループ使えるし、ナイスな感じです。
LEDとモード切替用のボタンスイッチを搭載してライトヘッドを作成する予定ですが、交換できるようにしたいですね。
最終的なソースコードをUPします。くだらないソースで、重ね重ねすみません。m(__)m
/** ToggleSwitch.h* Created on: 2013/10/12* Author: hiro* 使い方* ToggleSwitch.h 及び ToggleSwitch.cpp は[gr_common]の[include]フォルダにインポートする。* コンストラクタには使用するスイッチの値を渡す。 例: ToggleSwitch sw(PIN_SW) * 長押しボタンを使用する場合は、有効化する時間をコンストラクタの第二引数に渡す(ミリ秒)。 例: ToggleSwitch sw(PIN_SW,1000)* get_interval, set_interval は長押し有効化時間の取得・設定関数* ボタンをチェックするため、update関数を周期関数等により呼び出す* 押された回数をcount()で取得する。* increment()は押された回数を強制的にインクリメント(+1)するもの*/#include <RLduino78.h> #ifndef TOGGLESWITCH_H_#define TOGGLESWITCH_H_class ToggleSwitch {private: unsigned long m_start; // 長押しスイッチのON時刻の保持 unsigned long m_interval; // 長押しスイッチのON認識の時間間隔 int m_count; // スイッチのカウント数 int m_switch_no; // スイッチ番号の保持 boolean m_prev_condition; // 前回の状態の保持用 boolean m_curr_condition; // 今回の状態public: /* コンストラクタ 長押しボタン不使用。 */ ToggleSwitch(int sw_no) : m_start(0), m_interval(0), m_count(0), m_switch_no(sw_no), m_prev_condition(false),m_curr_condition(false) {} /* コンストラクタ 長押しボタン使用。 */ ToggleSwitch(int sw_no, unsigned long interval) : m_start(0), m_interval(interval), m_count(0), m_switch_no(sw_no), m_prev_condition(false),m_curr_condition(false) {} ~ToggleSwitch(){} /* デストラクタ */ unsigned long get_interval(); /* 長押し間隔を返す関数 */ void set_interval(unsigned long interval); /* 長押し間隔をセットする関数 */ int count(); /* ボタンの押された回数を返す関数 */ void update(); /* 更新 */ void increment(); /* 強制インクリメント */ void flash(); /* m_prev_condition と m_curr_condition値をfalseにする。 */}; #endif /* TOGGLESWITCH_H_ */
//ToggleSwitch.cpp#include <RLduino78.h> #include "ToggleSwitch.h"unsigned long ToggleSwitch::get_interval(){ return m_interval;}void ToggleSwitch::set_interval(unsigned long interval){ m_interval = interval;}int ToggleSwitch::count(){ return m_count;}void ToggleSwitch::flash(){ m_prev_condition = false; m_curr_condition = false;}void ToggleSwitch::update() { m_prev_condition = m_curr_condition; //ボタンOnでdigitalRead==0 m_curr_condition = digitalRead(m_switch_no)==0 ? true : false; //On→Offでカウント値をインクリメント if(m_prev_condition && !m_curr_condition) { if(m_interval == 0){ ++m_count; }else{ if(m_start!=0 && (millis()-m_start) >= m_interval) ++m_count; m_start = 0; } } //Off→OnでOn時間保持 if(!m_prev_condition && m_curr_condition) m_start = millis();}void ToggleSwitch::increment(){ ++m_count;}
/*GR-KURUMI Sketch Template Version: V1.02*/#include <RLduino78.h>#include "ToggleSwitch.h"const int MY_SW = 13; //ボタン(スイッチ)を使用するピンを設定const int MyLEDCount = 1; //LEDを使用する数を設定int MyLED[MyLEDCount];// Pin 22,23,24 are assigned to RGB LEDs.const unsigned long WAIT_TIME = 10000; //ボタンを放置した場合にロック状態に移行する時間を設定(ms)ToggleSwitch lsw(MY_SW,1000); //長押し用のインスタンス 第二引数に長押し時間は第二引数(ms)ToggleSwitch sw(MY_SW); //実際の操作用のインスタンス(長押しと同じボタンを使用する場合は同じ)int prev_count = 0;unsigned long change_time = 0;void LED_func1();void timer_interrupt(unsigned long u32ms){ lsw.update(); if(lsw.count() % 2 == 0) { change_time = 0; return; }else{ if(change_time == 0) { sw.flash(); change_time = millis(); } //WAIT_TIMEを超過した場合にlswをOff(強制インクリメント)にする。 if(change_time != 0 && (millis()-change_time) > WAIT_TIME) { lsw.increment(); return; } sw.update(); if(prev_count != sw.count()) change_time = millis(); prev_count = sw.count(); }}void setup() { //LED設定 MyLEDCount の値に合わせて設定すること。 MyLED[0] = 10; //MyLED[1] = xx; ・・・ for(int i=0; i<MyLEDCount; ++i){ pinMode(MyLED[i], OUTPUT); digitalWrite(MyLED[i], LOW); } //Switch設定 pinMode(MY_SW,INPUT); digitalWrite(MY_SW, HIGH); //タイマ設定 attachCyclicHandler(0,timer_interrupt,10); delay(100);}void setAllLEDs(int value){ for(int i=0; i<MyLEDCount; ++i) digitalWrite(MyLED[i],value);}void loop() { //sw.count()で押された回数を取得できるので、剰余を算出する事により動作を制御できる。 int tmp_cnt = sw.count() % 2; //←ここの数字は、実装するファンクション数にすること。 switch(tmp_cnt){ case 0: setAllLEDs(LOW); break; case 1: LED_func1(); break; //case 2: // LED_func2(); // break; ・・・ }}void LED_func1(){ for(int i=0; i<1; ++i){ digitalWrite(MyLED[i],HIGH); } delay(100); for(int i=0; i<1; ++i){ digitalWrite(MyLED[i],LOW); } delay(100);}
参考までにブレッドボードに組んだ動作中の写真をUPします。
チャタリングが発生するのと、いろいろな関数を実行させるとスイッチに問題が出たので修正しました。
スイッチをチェックするためのピンは割り込み端子 2 or 3 ピンを使用してattachInterruptを用いる。
チャタリングは一定時間の短時間の更新はスルーするようにしました。(安易な解決法かもしれませんが、、)
チャタリング対策は、ToggleSwitchクラスに内包した方が良いかもしれませんし、剰余を返すようにしても良いかもしれません。
あと、継承させて新しいクラスとした方が良いかどうかといったところでしょうか。
/*GR-KURUMI Sketch Template Version: V1.02*/#include <RLduino78.h>#include "ToggleSwitch.h"const int MY_SW = 2; //ボタン(スイッチ)を使用するピンを設定 割り込み番号0か1 (0: ピン2、1: ピン3)const int MyLEDCount = 1; //LEDを使用する数を設定const int CHATTERING_INTERVAL = 5; //スイッチのチャタリング対策の間歇時間int MyLED[MyLEDCount];// Pin 22,23,24 are assigned to RGB LEDs.const unsigned long WAIT_TIME = 10000; //ボタンを放置した場合にロック状態に移行する時間を設定(ms)ToggleSwitch lsw(MY_SW,1000); //長押し用のインスタンス 第二引数に長押し時間は第二引数(ms)ToggleSwitch sw(MY_SW); //実際の操作用のインスタンス(長押しと同じボタンを使用する場合は同じ)int prev_count = 0;unsigned long change_time = 0;void LED_func1();void LED_func2();void timer_interrupt(){ lsw.update(); if(lsw.count() % 2 == 0) { change_time = 0; return; }else{ if(change_time == 0) { sw.flash(); change_time = millis(); } //WAIT_TIMEを超過した場合にlswをOff(強制インクリメント)にする。 if(change_time != 0 && (millis()-change_time) > WAIT_TIME) { lsw.increment(); return; } if(millis() - change_time < CHATTERING_INTERVAL) return; //スイッチのチャタリング対策 sw.update(); if(prev_count != sw.count()) change_time = millis(); prev_count = sw.count(); }}void setup() { //LED設定 MyLEDCount の値に合わせて設定すること。 MyLED[0] = 10; //MyLED[1] = xx; ・・・ for(int i=0; i<MyLEDCount; ++i){ pinMode(MyLED[i], OUTPUT); digitalWrite(MyLED[i], LOW); } //Switch設定 pinMode(MY_SW,INPUT); digitalWrite(MY_SW, HIGH); //割り込み設定 attachInterrupt(0,timer_interrupt,CHANGE); delay(100);}void setAllLEDs(int value){ for(int i=0; i<MyLEDCount; ++i) digitalWrite(MyLED[i],value);}void loop() { //sw.count()で押された回数を取得できるので、剰余を算出する事により動作を制御できる。 int tmp_cnt = sw.count() % 4; //←ここの数字は、実装するファンクション数にすること。 switch(tmp_cnt){ case 0: setAllLEDs(LOW); break; case 1: setAllLEDs(HIGH); break; case 2: LED_func1(); break; case 3: LED_func2(); break; }}void LED_func1(){ for(int i=0; i<MyLEDCount; ++i){ digitalWrite(MyLED[i],HIGH); } delay(100); for(int i=0; i<MyLEDCount; ++i){ digitalWrite(MyLED[i],LOW); } delay(100);}void LED_func2(){ for(int j=0; j<3; ++j){ for(int i=0; i<MyLEDCount; ++i){ digitalWrite(MyLED[i],HIGH); } delay(300); for(int i=0; i<MyLEDCount; ++i){ digitalWrite(MyLED[i],LOW); } delay(300); } delay(1000);}