/*** Config part */// application IDconstuint32_t DEFAULT_APP_ID =0x1234abcd;// channelconstuint8_t DEFAULT_CHANNEL =13;// option bitsuint32_t OPT_BITS =0;// logical iduint8_t LID =0;/*** function prototype */MWX_APIRETtransmit();voidreceive();/*** application defs */constchar APP_FOURCHAR[] ="BAT1";// sensor valuesuint16_tau16AI[5];uint8_t u8DI_BM;
サンプルアクト共通宣言
長めの処理を関数化しているため、そのプロトタイプ宣言(送信と受信)
アプリケーション中のデータ保持するための変数
セットアップ setup()
voidsetup() { /*** SETUP section */ // init varsfor(auto&& x : au16AI) x =0xFFFF; u8DI_BM =0xFF; // load board and settingsauto&& set =the_twelite.settings.use<STG_STD>();auto&& brd =the_twelite.board.use<BRD_APPTWELITE>();auto&& nwk =the_twelite.network.use<NWK_SIMPLE>(); // settings: configure items set << SETTINGS::appname("BRD_APPTWELITE"); set << SETTINGS::appid_default(DEFAULT_APP_ID); // set default appID set << SETTINGS::ch_default(DEFAULT_CHANNEL); // set default channelset.hide_items(E_STGSTD_SETID::OPT_DWORD2, E_STGSTD_SETID::OPT_DWORD3, E_STGSTD_SETID::OPT_DWORD4, E_STGSTD_SETID::ENC_KEY_STRING, E_STGSTD_SETID::ENC_MODE);set.reload(); // load from EEPROM. OPT_BITS =set.u32opt1(); // this value is not used in this example. LID =set.u8devid(); // logical ID // the twelite main class the_twelite<< set // apply settings (appid, ch, power)<< TWENET::rx_when_idle(); // open receive circuit (if not set, it can't listen packts from others)if (brd.get_M1()) { LID =0; } // Register Network nwk << set // apply settings (LID and retry) ; // if M1 pin is set, force parent device (LID=0) nwk << NWK_SIMPLE::logical_id(LID); // write logical id again. /*** BEGIN section */ // start ADC captureAnalogue.setup(true, ANALOGUE::KICK_BY_TIMER0); // setup analogue read (check every 16ms)Analogue.begin(pack_bits( BRD_APPTWELITE::PIN_AI1, BRD_APPTWELITE::PIN_AI2, BRD_APPTWELITE::PIN_AI3, BRD_APPTWELITE::PIN_AI4, PIN_ANALOGUE::VCC)); // _start continuous adc capture. // Timer setupTimer0.begin(32,true); // 32hz timer // start button checkButtons.setup(5); // init button manager with 5 history table.Buttons.begin(pack_bits( BRD_APPTWELITE::PIN_DI1, BRD_APPTWELITE::PIN_DI2, BRD_APPTWELITE::PIN_DI3, BRD_APPTWELITE::PIN_DI4),5, // history count4); // tick delta (change is detected by 5*4=20ms consequtive same values) the_twelite.begin(); // start twelite! /*** INIT message */ Serial <<"--- BRD_APPTWELITE ---"<< mwx::crlf; Serial <<format("-- app:x%08x/ch:%d/lid:%d",the_twelite.get_appid(),the_twelite.get_channel(),nwk.get_config().u8Lid )<< mwx::crlf; Serial <<format("-- pw:%d/retry:%d/opt:x%08x",the_twelite.get_tx_power(),nwk.get_config().u8RetryDefault, OPT_BITS )<< mwx::crlf;}
大まかな流れは、各部の初期設定、各部の開始となっています。
各種ビヘイビアオブジェクトの登録
auto&& set =the_twelite.settings.use<STG_STD>();auto&& brd =the_twelite.board.use<BRD_APPTWELITE>();auto&& nwk =the_twelite.network.use<NWK_SIMPLE>();
// インタラクティブモードの初期化auto&& set =the_twelite.settings.use<STG_STD>();set << SETTINGS::appname("BRD_APPTWELITE");set << SETTINGS::appid_default(DEFAULT_APP_ID); // set default appIDset << SETTINGS::ch_default(DEFAULT_CHANNEL); // set default channelset.hide_items(E_STGSTD_SETID::OPT_DWORD2, E_STGSTD_SETID::OPT_DWORD3, E_STGSTD_SETID::OPT_DWORD4, E_STGSTD_SETID::ENC_KEY_STRING, E_STGSTD_SETID::ENC_MODE);set.reload(); // load from EEPROM.OPT_BITS =set.u32opt1(); // this value is not used in this example.LID =set.u8devid(); // logical ID;
Timer0は32Hzで動作しています。タイマー割り込みが発生直後の loop() で available になります。つまり、秒32回の処理をします。ここでは、ちょうど1秒になったところで送信処理をしています。
if (Timer0.available()) {staticuint8_t u16ct; u16ct++;if (u8DI_BM !=0xFF&&au16AI[0] !=0xFFFF) { // finished the first captureif ((u16ct %32) ==0) { // every 32ticks of Timer0transmit(); } }}
MWX_APIRETtransmit() {if (auto&& pkt =the_twelite.network.use<NWK_SIMPLE>().prepare_tx_packet()) {auto&& set =the_twelite.settings.use<STG_STD>();if (!set.is_screen_opened()) { Serial <<"..DI="<<format("%04b ", u8DI_BM); Serial <<format("ADC=%04d/%04d/%04d/%04d ",au16AI[1],au16AI[2],au16AI[3],au16AI[4]); Serial <<"Vcc="<<format("%04d ",au16AI[0]); Serial <<" --> transmit"<< mwx::crlf; } // set tx packet behavior pkt <<tx_addr(u8devid ==0?0xFE:0x00) // 0..0xFF (LID 0:parent, FE:child w/ no id, FF:LID broad cast), 0x8XXXXXXX (long address)<<tx_retry(0x1) // set retry (0x1 send two times in total)<<tx_packet_delay(0,50,10); // send packet w/ delay (send first packet with randomized delay from 100 to 200ms, repeat every 20ms) // prepare packet payloadpack_bytes(pkt.get_payload() // set payload data objects.,make_pair(APP_FOURCHAR,4) // string should be paired with length explicitly.,uint8_t(u8DI_BM) );for (auto&& x : au16AI) {pack_bytes(pkt.get_payload(),uint16_t(x)); // adc values } // do transmit returnpkt.transmit(); }returnMWX_APIRET(false,0);}
auto&& set =the_twelite.settings.use<STG_STD>();if (!set.is_screen_opened()) { //インタラクティブモード画面中ではない!}
インタラクティブモードの画面が表示されているときは、画面出力を抑制します。
パケットの送信設定
pkt <<tx_addr(u8devid ==0?0xFE:0x00) // 0..0xFF (LID 0:parent, FE:child w/ no id, FF:LID broad cast), 0x8XXXXXXX (long address)<<tx_retry(0x1) // set retry (0x3 send four times in total)<<tx_packet_delay(0,50,10); // send packet w/ delay (send first packet with randomized delay from 100 to 200ms, repeat every 20ms)
// prepare packet payloadpack_bytes(pkt.get_payload() // set payload data objects.,make_pair(APP_FOURCHAR,4) // string should be paired with length explicitly.,uint8_t(u8DI_BM));for (auto&& x : au16AI) {pack_bytes(pkt.get_payload(),uint16_t(x)); // adc values}
voidon_rx_packet(packet_rx& rx,bool_t&handled) { auto&& set =the_twelite.settings.use<STG_STD>(); Serial <<format("..receive(%08x/%d) : ",rx.get_addr_src_long(),rx.get_addr_src_lid()); // expand the packet payloadcharfourchars[5]{};auto&& np =expand_bytes(rx.get_payload().begin(),rx.get_payload().end(),make_pair((uint8_t*)fourchars,4) // 4bytes of msg ); // check headerif (strncmp(APP_FOURCHAR, fourchars,4)) { return; } // read rest of payloaduint8_t u8DI_BM_remote =0xff;uint16_tau16AI_remote[5];expand_bytes(np,rx.get_payload().end(), u8DI_BM_remote,au16AI_remote[0],au16AI_remote[1],au16AI_remote[2],au16AI_remote[3],au16AI_remote[4] ); Serial <<format("DI:%04b", u8DI_BM_remote &0x0F);for (auto&& x : au16AI_remote) { Serial <<format("/%04d", x); } Serial << mwx::crlf; // set local DOdigitalWrite(BRD_APPTWELITE::PIN_DO1, (u8DI_BM_remote &1) ? HIGH : LOW);digitalWrite(BRD_APPTWELITE::PIN_DO2, (u8DI_BM_remote &2) ? HIGH : LOW);digitalWrite(BRD_APPTWELITE::PIN_DO3, (u8DI_BM_remote &4) ? HIGH : LOW);digitalWrite(BRD_APPTWELITE::PIN_DO4, (u8DI_BM_remote &8) ? HIGH : LOW); // set local PWM : duty is set 0..1024, so 1023 is set 1024.Timer1.change_duty(au16AI_remote[1] ==1023?1024:au16AI_remote[1]);Timer2.change_duty(au16AI_remote[2] ==1023?1024:au16AI_remote[2]);Timer3.change_duty(au16AI_remote[3] ==1023?1024:au16AI_remote[3]);Timer4.change_duty(au16AI_remote[4] ==1023?1024:au16AI_remote[4]);}
// set local DOdigitalWrite(BRD_APPTWELITE::PIN_DO1, (u8DI_BM_remote &1) ? HIGH : LOW);digitalWrite(BRD_APPTWELITE::PIN_DO2, (u8DI_BM_remote &2) ? HIGH : LOW);digitalWrite(BRD_APPTWELITE::PIN_DO3, (u8DI_BM_remote &4) ? HIGH : LOW);digitalWrite(BRD_APPTWELITE::PIN_DO4, (u8DI_BM_remote &8) ? HIGH : LOW);// set local PWM : duty is set 0..1024, so 1023 is set 1024.Timer1.change_duty(au16AI_remote[1] ==1023?1024:au16AI_remote[1]);Timer2.change_duty(au16AI_remote[2] ==1023?1024:au16AI_remote[2]);Timer3.change_duty(au16AI_remote[3] ==1023?1024:au16AI_remote[3]);Timer4.change_duty(au16AI_remote[4] ==1023?1024:au16AI_remote[4]);