This act includes the following:
- Wireless packet transmission (press ’t’ key)
- Sleep (press ’s’ key)
- Input from serial port -
Serial
- Digital (button) input -
Buttons
setup()
void setup() {
/*** SETUP section */
tx_busy = false;
// the twelite main class
the_twelite
<< TWENET::appid(APP_ID) // set application ID (identify network group)
<< TWENET::channel(CHANNEL) // set channel (physical channel)
<< TWENET::rx_when_idle(); // open receive circuit (if not set, it can't listen packets from others)
// Register Network
auto&& nwk = the_twelite.network.use<NWK_SIMPLE>();
nwk << NWK_SIMPLE::logical_id(0xFE); // set Logical ID. (0xFE means a child device with no ID)
/*** BEGIN section */
Buttons.begin(pack_bits(PIN_BTN), 5, 10); // check every 10ms, a change is reported by 5 consecutive values.
the_twelite.begin(); // start twelite!
/*** INIT message */
Serial << "--- Scratch act ---" << mwx::crlf;
}
Configure the_twelite
with application ID APP_ID
, wireless channel CHANNEL
, and enable reception.
Also, generate nwk
and specify child address 0xFE
. This address means a child device without a specified address.
Configurable addresses are 0x00
: parent, 0x01
~0xEF
: child, 0xFE
: unspecified child address.
Addresses specified as destinations are 0x00
for parent, 0x01
~0xEF
for specific child, 0xFE
for any child, and 0xFF
for any address including the parent.
Also, initialize the Buttons
object. This is a chatter suppression algorithm using consecutive references. If the same value is detected 5 times consecutively every 10ms, the port (only PIN_BTN
) is confirmed as HIGH
or LOW
. The function pack_bits(N1, N2, ..)
generates a bitmap by 1UL<<N1 | 1UL << N2 | ...
.
the_twelite.begin(); // start twelite!
This is the procedure to start the_twelite
. Although it did not appear in act0..4
, if you configure the_twelite
or register various behaviors, always call this.
begin()
void begin() {
Serial << "..begin (run once at boot)" << mwx::crlf;
}
Called only once after setup()
at startup. Only displays a message.
loop()
Button (switch) input detection
if (Buttons.available()) {
uint32_t bm, cm;
Buttons.read(bm, cm);
if (cm & 0x80000000) {
// the first capture.
}
Serial << int(millis()) << ":BTN" << format("%b") << mwx::crlf;
}
Using consecutive references by Buttons
, the state is confirmed. When the button state changes, output to serial.
Input from serial
while(Serial.available()) {
int c = Serial.read();
Serial << '[' << char(c) << ']';
switch(c) {
case 'p': ... // Display millis()
case 't': ... // Send wireless packet (vTransmit)
if (!tx_busy) {
tx_busy = Transmit();
if (tx_busy) {
Serial << int(millis()) << ":tx request success! ("
<< int(tx_busy.get_value()) << ')' << mwx::crlf;
} else {
Serial << int(millis()) << ":tx request failed" << mwx::crlf;;
}
}
case 's': ... // Sleep
Serial << int(millis()) << ":sleeping for " << 5000 << "ms" << mwx::crlf << mwx::flush;
the_twelite.sleep(5000);
break;
}
}
If Serial.available()
is true
, input is stored from the serial port. Read one character from serial and process according to the input character.
Input ’t’ to send wireless
When ’t’ is input, transmission is performed. This sample uses a tx_busy
flag to avoid continuous input.
Since transmission requests are queued up to a certain number, it is possible to stack requests within the queue range (3 packets).
Below is an example of processing when the if(!tx_busy)
check is removed and ’tttt’ is entered continuously. The 4th request fails because the queue is full.
The pkt
object obtained by .prepare_tx_packet()
of Transmit()
becomes false
.
Transmission timing is randomized, so completion is not in the order of request.
--- Scratch act ---
..begin (run once at boot)
[t]11591:Transmit()
11592:tx request success! (1)
[t]11593:Transmit()
11593:tx request success! (2)
[t]11594:Transmit()
11595:tx request success! (3)
[t]11595:Transmit()
TX QUEUE is FULL
11596:tx request failed
11654:tx completed!(id=2, stat=1)
11719:tx completed!(id=3, stat=1)
11745:tx completed!(id=1, stat=1)
Input ’s’ to sleep
the_twelite.sleep(5000);
Sleep for 5000ms = 5 seconds. After waking up, wakeup()
is executed.
wakeup()
void wakeup() {
Serial << int(millis()) << ":wake up!" << mwx::crlf;
}
Called first upon waking from sleep. Only displays a message.
Transmit()
MWX_APIRET Transmit() {
Serial << int(millis()) << ":Transmit()" << mwx::crlf;
if (auto&& pkt = the_twelite.network.use<NWK_SIMPLE>().prepare_tx_packet()) {
// set tx packet behavior
pkt << tx_addr(0xFF) // Broadcast communication
<< tx_retry(0x1) // Retry once
<< tx_packet_delay(100,200,20); // Transmit delay between 100-200ms, retry interval 20ms
// Specify transmission data (decided by application)
pack_bytes(pkt.get_payload()
, make_pair("SCRT", 4) // 4-character identifier
, uint32_t(millis()) // Timestamp
);
// Request transmission
return pkt.transmit();
} else {
// Failed at .prepare_tx_packet() stage (transmission queue full)
Serial << "TX QUEUE is FULL" << mwx::crlf;
return MWX_APIRET(false, 0);
}
}
Minimal procedure to request transmission.
At the time this function exits, the request has not yet been executed. You need to wait a while. In this example, a delay of 100-200ms before transmission start is set, so transmission will start at the earliest 100ms later.
on_tx_comp()
void on_tx_comp(mwx::packet_ev_tx& ev, bool_t &b_handled) {
Serial << int(millis()) << ":tx completed!"
<< format("(id=%d, stat=%d)", ev.u8CbId, ev.bStatus) << mwx::crlf;
tx_busy = false; // clear tx busy flag.
}
Called when transmission completes. ev
contains transmission ID and completion status.
on_rx_packet()
void on_rx_packet(packet_rx& rx, bool_t &handled) {
Serial << format("rx from %08x/%d",
rx.get_addr_src_long(), rx.get_addr_src_lid()) << mwx::crlf;
}
When a packet is received, display the sender’s address information.