BRD_APPTWELITE
IO communication (basic function of standard application App_Twelite)
最終更新
IO communication (basic function of standard application App_Twelite)
最終更新
This is a sample using board support <BRD_APPTWELITE>
, which assumes the same wiring as required by App_TweLite.
This ACT includes:
Transmission and reception of wireless packets
Interactive settings mode -
Digital (button) input -
analog input -
This sample cannot communicate with App_TweLite.
Read M1 to determine the parent or child unit.
Reads the value of DI1-DI4; the Buttons class reduces the effect of chattering, so that changes are notified only when the values are the same consecutively. Communication is performed when there is a change.
Reads the value of AI1-AI4.
Sends the values of DI1-4, AI1-4, and VCC to a child unit if it is the parent unit, or to the parent unit if it is a child unit, every DI change or every 1 second.
Set to DO1-4 or PWM1-4 depending on the value of the received packet.
Parent Node
Child Node
It also includes <STG_STD>
to add Interactive settings mode.
sample-act common declaration
Its prototype declarations (send and receive), since the longer process is functionalized
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.
Register BEHAVIOR objects to determine system behavior. It can be an Interactive settings mode, board support, or a network description of wireless packets.
It will not work unless registered within setup()
.
Initialize the Interactive settings mode. First, a set
object is obtained. Then, the following process is performed.
Set the application name to "BRD_APPTWELITE"
(used in the menu)
Rewrite default Application ID and CHANNEL values
Delete unnecessary items
reads configuration values saved by set.reload()
.
Copy the values of OPT_BITS
and LID
into the variables
Below is an example screen. + + + and + three times with a pause of 0.2 to 1 second to bring up the Interactive settings mode screen.
This object behaves as the core of TWENET.
Register a board (this ACT registers <BRD_APPTWELITE>
). Specify the name of the board you want to register with <>
after use
as follows.
The return value obtained by universal reference (auto&&
) is a board object of reference type. This object contains board-specific operations and definitions. The following example uses the board object to check the status of the M1 pin: if the M1 pin is LO, set LID = 0, i.e., the Parent Node address.
Initial configuration is required to make the the_twelite work. Application ID and wireless CHANNEL settings are mandatory.
Use <<
to apply the setting to the_twelite
.
TWENET::rx_when_idle()
Specification to open the receive circuit.
Next, register the network.
The first line is written in the same way as for board registration, where <>
is <NWK_SIMPLE>
.
The second and third lines are settings for <NWK_SIMPLE>
. The first one reflects the value of the settings in Interactive settings mode. The items to be reflected are LID and the number of retransmissions. In this application, LID is set again in the third line because LID=0 may be set depending on the state of the M1 pin.
Class object that handles ADCs (analog-to-digital converters).
The Initialization is performed by Analogue.setup()
. The parameter true
specifies to wait in place until the ADC circuit is stable; the second parameter specifies to start the ADC synchronously with Timer0.
To start the ADC, call Analogue.begin()
. The parameter is a bitmap corresponding to the pin of the ADC target.
The pack_bits()
function is used to specify a 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.
Parameters and BRD_APPTWELITE::
specified as PIN_AI1..4
are defined, corresponding to AI1..AI4 used in App_Twelite. AI1=ADC1, AI2=DIO0, AI3=ADC2, AI4=DIO2 and so on are assigned. PIN_ANALOGUE. PIN_ANALOGUE::
defines the list of pins available for ADC.
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 chattering (sliding) on mechanical buttons.
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.
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. Since 4
is specified, the HIGH and LOW states are determined when the same value is detected five times in a row every 4ms.
Since App_Twelite uses a timer origin to control the application, the same timer interrupt/event should be run in this ACT. Of course, you can also use the system's TickTimer, which runs every 1 ms.
The first parameter in the above example specifies a timer frequency of 32 Hz; setting the second parameter to `true' enables software interrupts.
After calling Timer0.begin()
, the timer starts running.
Execute the_twelite.begin()
at the end of the setup()
function.
Serial objects can be used without initialization or initiation procedures.
This sample displays some system configuration values as a startup message. The Serial
object is given a string of type const char*, a string of type int (no other integer types), a format()
that behaves almost identically to printf, and a crlf
that outputs newline characters to the << operator.
Loop functions 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 of the 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.
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,... in order from bit0. For example, for DIO12, HIGH / LOW can be determined by evaluating bp & (1UL << 12)
. The bit that is set to 1 is HIGH.
Next, the values are extracted from the bitmap and stored in u8DI_BM
. Here, the collect_bits()
function provided by the MWX library is used.
collect_bits()
takes an integer argument of bit positions similar to pack_bits()
above. It is a function with a variable number of arguments and arranges the parameters as many as necessary. In the above process, bit0 is stored in u8DI_BM as the value of DI1, bit1 as the value of DI2, bit2 as the value of DI3, and bit3 as the value of DI4.
In App_Twelite, since wireless transmission is performed when there is a change from DI1 to DI4, the transmission process is performed starting from Buttons.available()
. The details of the transmit()
process are described below.
It becomes available at loop()
immediately after the analog-to-digital conversion of the ADC is completed. Until the next ADC starts, data can be read back as if it was acquired immediately before.
Use the Analogue.read()
or Analogue.read_raw()
method to read ADC values. read()
is the value converted to mV, read_raw()
is the ADC value of 0..1023. The parameter is the pin number of ADC, which is defined in PIN_ANALOGUE::
or BRD_APPTWELITE::
.
ADC values that are executed cyclically may read more recent values prior to the AVAILABLE notification, depending on the timing.
Since this ACT processes at a relatively slow cycle of 32 Hz, it is not a problem if the processing is done immediately after the AVAILABLE decision, but if the conversion cycle is short, or if you are doing a relatively long process in loop()
, be careful.
In Analogue
, you can specify a callback function that will be called from within the interrupt handler after the conversion is complete. For example, this callback function will store the value in the FIFO queue, and the application loop will perform asynchronous processing such as sequential reading of the queue value.
The Timer0
runs at 32 Hz. It becomes available at loop()
immediately after a timer interrupt occurs. In other words, it processes 32 times per second. Here, the transmission is processed when it reaches exactly 1 second.
AppTwelite performs a periodic transmission about every second. When Timer0
becomes available, it increments u16ct
. Based on this counter value, transmit()
is called to send a radio packet when the count is completed 32 times.
The value judgment of u8DI_BM
and au16AI[]
is whether or not it is just after initialization. If the values of DI1..DI4 and AI1..AI4 are not yet stored, nothing is done.
This function requests TWENET to send a radio 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.
MWX_APIRET
is a class that handles return values with data members of type uint32_t
, where MSB (bit31) is success/failure and the rest are used as return values.
Get a network object with the_twelite.network.use<NWK_SIMPLE>()
. Use that object to get a pkt
object with .prepare_tx_packet()
.
Here it is declared in a conditional expression in an 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 the TWENET send request queue is free and the send request is accepted, or false
if there is no free queue.
Suppresses screen output when Interactive settings mode screen is displayed.
Packets are configured using the <<
operator as in the initialization settings of the_twelite
.
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. The 1
in the example sends one retry, i.e., a total of two packets. Sending only one wireless packet will 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, the second is the maximum wait time, in this case approximately from 0 to 50 ms after issuing a request to send. The third is the retransmission interval. The third is the retransmission interval, meaning that a retransmission is performed every 10 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.
Be aware of the data order of the data payload for correct transmission and reception. In this example, the data order is as follows. Construct the data payload according to this data order.
Let's actually construct the data structure of the above data payload. The data payload can be referenced as a container of type simplbuf<uint8_t>
by 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 parameter after that is a variable number of arguments, pack_bytes
, specifying the required number of values of the corresponding type. 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 to avoid confusion of string types (specifically, including or excluding 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.
The fourth line is of type uint8_t
and writes a bitmap of DI1..DI4.
Lines 7-9 write the values of the au16AI
array in sequence. The values are of type uint16_t
and are 2 bytes, but are written in big-endian order.
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. It returns a return value of type MWX_APIRET
, which is not used in this ACT.
When a wireless packet is received, on_rx_packet()
is called as a receive event.
Here, the values of DI1...DI4 and AI1...AI4 communicated by the other party are set to its own DO1...DO4 and PWM1...PWM4.
First, the data rx
of the received packet is passed as a parameter. From rx
the address information and data payload of the wireless packet is accessed. The parameter handled
is not normally used.
Received packet data is referenced to the source address (32-bit long address and 8-bit logical address) and other information. Output is suppressed when the Interactive settings mode screen is displayed.
The MWX library provides a function expand_bytes()
as a counterpart to pack_bytes()
used in transmit()
.
The first line declares an array of type char
for data storage. The size of the array is 5 bytes because the null character is included at the end for convenience in character output, etc. The trailing {}
specifies initialization. The trailing {}
specifies initialization, and although it is sufficient to set the fifth byte to 0, here the entire array is initialized in the default way, that is, to 0
.
The 4-byte string is extracted by expand_bytes()
in the second line. The reason for not specifying the container type in the parameters is that we need to know the read position to read this continuation. the first parameter specifies the first iterator of the container (uint8_t*
pointer), which can be obtained by the .begin()
. The second parameter is an iterator that points to the next to the end of the container and can be retrieved with the .end()
method. The second parameter is used to avoid reading beyond the end of the container.
The third variable to read is specified, again by make_pair
, which is a pair of string array and size.
If the identifier in the 4-byte string read is different from the identifier specified in this ACT, this packet is not processed.
The next step is to get the data part: store the values of DI1..DI4 and AI1..AI4 in separate variables.
The first parameter is the return value np
of the previous expand_bytes()
. The second parameter is the same.
The third and subsequent parameters are variables of the matching type alongside the data payload, in the same order as the sender's data structure. Once this process is complete, the specified variable will contain the value read from the payload.
Output to serial port for confirmation. Output is suppressed when the Interactive settings mode screen is displayed.
We use format()
because we need to format output of numbers. helper class that allows the same syntax as printf()
for the >>
operator, but limits the number of arguments to four. (Serial.printfmt()
has no limit on the number of arguments.)
The first line "DI:%04b"
prints a 4-digit bitmap of DI1..DI4, like "DI:0010"
The third line "/%04d"
prints the values of Vcc/AI1..AI4 as integers, like "/3280/0010/0512/1023/"
The fifth line mwx::crlf
prints a newline string.
Now that the necessary data has been extracted, all that remains is to change the values of DO1..DO4 and PWM1..PWM4 on the board.
digitalWrite()
changes the value of the digital output, the first parameter is the pin number and the second is HIGH
(Vcc level) or LOW
(GND level).
Timer?.change_duty()
changes the duty ratio of the PWM output. Specify a duty ratio of 0..1024 for the parameter. Note that the maximum value is not 1023 (the maximum value is 1024, a power of 2, due to the high cost of the division performed in the library). Setting the value to 0
will result in an output equivalent to the GND level, and setting it to 1024
will result in an output equivalent to the Vcc level.
At a minimum, wire M1=GND, DI1:button, DO1:LED.
At a minimum, wire M1=open, DI1:button, DO1:LED.
Include <TWELITE>
in all ACTs. Here is a simple network and board support <BRD_APPTWELITE>
should be included.
set
reflects some of the settings (Application ID, radio channel, etc.) read from Interactive settings mode. The items to be reflected are described in .