PingPong
最終更新
最終更新
Send a PING wireless packet from one of the two serially connected TWELITEs and receive a PONG wireless packet back from the other.
This ACT includes.
Sending a prompt response from the receipt of a wireless packet
Transmission with direct address of the peer
Input from serial port -
Digital (button) input -
Analogue input -
Two of any of the following.
connected to UART with products/TWE-Lite-DIP/index.html), etc.
Sample act common declarations
Prototype declarations for longer processes (sending and receiving), since they are made into functions
Variables for holding data in the application
The general flow of the program is the initial setup of each section and the start of each section.
This object is the core class object for manipulating TWENET.
the_twelite
に設定を反映するには <<
を用います。
Use <<
to reflect the setting in the_twelite
.
TWENET::appid(APP_ID)
to specify the Application ID.
TWENET::channel(CHANNEL)
to specify the channel.
TWENET::rx_when_idle()
Specifies that the receive circuit is open.
Next, register the network.
The first line is written in the same way as the board registration, specifying <>
as <NWK_SIMPLE>
.
The second line specifies <NWK_SIMPLE>
, specifying 0xFE
(WK_SIMPLE
is a Child Node with an unset ID).
The third line specifies the maximum number of relays. This explanation does not touch on relaying, but packets are relayed when operating with multiple units.
Execute the_twelite.begin()
at the end of the setup()
function.
Class object that handles ADCs (analog-to-digital converters).
Initialization Analogue.setup()
. The parameter true
specifies to wait in place until the ADC circuit is stable.
To start the ADC, call Analogue.begin()
. The parameter is a bitmap corresponding to the pin to be ADC'd.
The pack_bits()
function is used to specify the bitmap. It is a function with variable number of arguments, each argument specifies a bit position to be set to 1. For example, pack_bits(1,3,5)
returns the binary value 101010
. This function has the constexpr
specification, so if the parameters are constants only, they are expanded to constants.
The parameters are specified as PIN_ANALOGUE::A1
(ADC0) and PIN_ANALOGUE::VCC
(module supply voltage).
The second parameter is specified as 50
, and the ADC operation is started by default with TickTimer, which is set to
Detects changes in DIO (digital input) values; Buttons only detect a change in value after the same value has been detected a certain number of times in order to reduce the effects of mechanical button chattering.
Initialization is done with Buttons.setup()
. The parameter 5 is the number of detections required to determine the value, but it is the maximum value that can be set. Internally, the internal memory is allocated based on this number.
The start is done with Buttons.begin()
The first parameter is the DIO to be detected. The second parameter is the number of detections required to determine the state. The third parameter is the detection interval. Since 10
is specified, the HIGH and LOW states are determined when the same value is detected five times in a row every 10 ms.
Serial objects can be used without initialization or initiation procedures.
Outputs a string to the serial port. mwx::crlf
is a newline character.
Loop function are called as callback functions from the main loop of the TWENET library. The basic description here is to wait for the object to be used to become available and then process it. This section describes the use of some objects used in ACT.
The main loop of the TWENET library processes incoming packets and interrupt information stored in the FIFO queue in advance as events, after which loop()
is called. After exiting loop()
, the CPU enters DOZE mode and waits until a new interrupt occurs with low current consumption.
Therefore, code that assumes the CPU is always running will not work well.
While Serial.available()
is true
, there is input from the serial port. The data is stored in the internal FIFO queue, so there is some leeway, but it should be read out promptly. To read data, call Serial.read()
.
Here, the vTransmit()
function is called to send a PING packet in response to a 't'
key input.
It becomes available at the timing when a change in DIO (digital IO) input is detected, and is read by Buttons.read()
.
The first parameter is a bitmap of the HIGH/LOW of the current DIO, ordered from bit0 to DIO0,1,2,... . and so on, starting from bit 0. For example, for DIO12, HIGH / LOW can be determined by evaluating btn_state & (1UL << 12)
. If the bit is set to 1, it is HIGH.
The vTransmit()
is called at the timing when the button is released except for the initial confirmation. To make the timing of the press (! (btn_state && (1UL << PIN_BTN)))
to invert the condition logically.
This function requests TWENET to send a wireless packet. At the end of this function, the wireless packet is not yet processed. The actual transmission will be completed in a few ms or later, depending on the transmission parameters. This section describes typical transmission request methods.
Get a network object with the_twelite.network.use<NWK_SIMPLE>()
. Use that object to get a pkt
object by .prepare_tx_packet()
.
Here it is declared in the conditional expression of the if statement. The declared pkt
object is valid until the end of the if clause. pkt object gives a response of type bool, which here is true
if there is a free space in TWENET's send request queue and the send request is accepted, or false
if there is no space.
Packets are configured using the <<
operator as in the_twelite
initialization setup.
Specify the destination address in the tx_addr()
parameter. If it is 0x00
, it means that you are the Child Node and broadcast to the Parent Node, and if it is 0xFE
, it means that you are the Parent Node and broadcast to any Child Node.
The tx_retry()
parameter specifies the number of retransmissions. In the example 3
means that the number of retransmissions is 3, i.e., the packet is sent 4 times in total. Sending only one wireless packet may fail a few percent of the time even under good conditions.
tx_packet_delay()
Sets the transmission delay. The first parameter is the minimum wait time to start sending and the second is the maximum wait time. The third is the retransmission interval. The third is the retransmission interval, meaning that a retransmission is performed every 20 ms after the first packet is sent.
Payload means a loaded item, but in wireless packets it is often used to mean "the main body of data to be sent". In addition to the main body of data, the data in a wireless packet also contains some auxiliary information, such as address information.
For correct transmission and reception, please be aware of the data order of the data payload. In this example, the data order is as follows. Construct the data payload according to this data order.
The data payload can contain 90 bytes (actually a few more bytes).
Every byte in an IEEE802.15.4 wireless packet is precious. There is a limit to the amount of data that can be sent in a single packet. If a packet is split, the cost of the split packet is high because it must take into account transmission failures. Also, sending one extra byte consumes energy equivalent to approximately 16 µs x current during transmission, which can be significant, especially for battery-powered applications. {endhint %}
Let's actually build the data structure of the above data payload. The data payload can be referenced as a container of type simplbuf<uint8_t>
via pkt.get_payload()
. In this container, we build the data based on the above specification.
It can be written as above, but the MWX library provides an auxiliary function pack_bytes()
for data payload construction.
The first parameter of pack_bytes
specifies the container. In this case, it is pkt.get_payload()
.
The parameters after that are variable arguments, specifying as many values of the corresponding type in pack_bytes
as needed. The pack_bytes
internally calls the .push_back()
method to append the specified value at the end.
The third line, make_pair()
, is a standard library function to generate std::pair
. This is specified to avoid confusion of string types (specifically, whether or not to include null characters when storing payloads). The first parameter of make_pair()
is the string type (char*
, uint8_t*
, uint8_t[]
, etc.) The second parameter is the number of bytes to store in the payload.
Lines 4, 5, and 6 store values of numeric types (uint8_t
, uint16_t
, uint32_t
). Numeric types such as signed, or even the same numeric type such as char
are cast to the three types listed on the left and submitted.
analogRead()
and analogRead_mv()
get the result of ADC. The former is the ADC value (0..1023) and the latter is the voltage[mv](0..2470). The supply voltage of the module is read internally from the value of the voltage divider resistor, so we use adalogRead_mv()
to perform that conversion.
This completes the packet preparation. Now all that remains is to make a request for transmission.
Packets are sent using the pkt.transmit()
method of the pkt
object.
This is the process when there is an incoming packet.
First, the data of the incoming packet is passed as parameter rx
. From rx
, the address information and data payload of the wireless packet is accessed.
In the next line, the received packet data refers to the source address (32-bit long address and 8-bit logical address) and other information.
The MWX library provides a function expand_bytes()
as a counterpart to pack_bytes()
used in transmit()
.
Lines 1 through 3 specify variables to store data.
The first parameter specifies the first iterator of the container (a uint8_t*
pointer), which can be retrieved by the .begin()
method. The second parameter is the next iterator after the end of the container and can be retrieved with the .end()
method.
The third and subsequent parameters enumerate variables. The payloads are read and stored in the order in which they are listed.
The process sends a PONG message if the identifier of the 4-byte string read in msg
is "PING"
.
It then displays information on packets that have arrived.
The format()
is used because numeric formatting output is required. helper class that allows the same syntax as printf() for >>
operators, but limits the number of arguments to a maximum of 8 (for 32-bit parameters). (A compile error will occur if the limit is exceeded. Note that Serial.printfmt()
has no limit on the number of arguments.)
The mwx::crlf
specifies a newline character (CR LF), and mwx::flush
waits for completion of output. (mxw::flush
may be written as Serial.flush()
)
Include <TWELITE>
in all ACTs. Here, the simple network should be included.