OPEnSLab-OSU / Loom

Arduino library for Internet of Things Rapid Prototyping in environmental sensing
GNU General Public License v3.0
26 stars 3 forks source link

Test Loom_nRF - Winnie #155

Closed winniiew closed 3 years ago

winniiew commented 3 years ago

Arduino: 1.8.15 (Windows 10), Board: "Loomified Feather M0, Arduino, Off, Wifi, Enabled, Enabled, Disabled, Disabled, On"

WARNING: library RF24Network claims to run on avr, esp8266 architecture(s) and may be incompatible with your current board which runs on samd architecture(s).

WARNING: library RF24 claims to run on avr, arm, x86, esp8266, esp32 architecture(s) and may be incompatible with your current board which runs on samd architecture(s).

c:/users/winni/appdata/local/arduino15/packages/loom/tools/arm-none-eabi-gcc/10-2020-q4/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: C:\Users\winni\AppData\Local\Temp\arduino_build_875468/nrf24_test.ino.elf section .text' will not fit in regionFLASH'

c:/users/winni/appdata/local/arduino15/packages/loom/tools/arm-none-eabi-gcc/10-2020-q4/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: region `FLASH' overflowed by 1648 bytes

collect2.exe: error: ld returned 1 exit status

exit status 1

Error compiling for board Loomified Feather M0.

WARNING: library RF24Network claims to run on avr, esp8266 architecture(s) and may be incompatible with your current board which runs on samd architecture(s).

WARNING: library RF24 claims to run on avr, arm, x86, esp8266, esp32 architecture(s) and may be incompatible with your current board which runs on samd architecture(s).

winniiew commented 3 years ago
///////////////////////////////////////////////////////////////////////////////

// This is a basic example of receiving data via nRF.
// While you can do a variety of things with the received data, this example
// simply prints it and logs it to an SD Card

// The corresponding example is nRF > Transmit

// These two examples are the Loom equivalent of the basic RX / TX nRF
// examples

// See https://openslab-osu.github.io/Loom/html/class_loom__n_r_f.html
// for details of nRF config options

///////////////////////////////////////////////////////////////////////////////

#include <Loom.h>

// Include configuration
const char* json_config =
#include "config.h"
;

// In Tools menu, set:
// Internet  > Disabled
// Sensors   > Enabled
// Radios    > Enabled
// Actuators > Disabled
// Max       > Disabled

using namespace Loom;

Loom::Manager Feather{};

void setup()
{
  pinMode(5, OUTPUT);
  digitalWrite(5, LOW); // Sets pin 5, the pin with the 3.3V rail, to output and enables the rail
  pinMode(6, OUTPUT);
  digitalWrite(6, HIGH); // Sets pin 6, the pin with the 5V rail, to output and enables the rail
  while(!Serial){}

    Feather.begin_serial(true,true);
    Feather.parse_config(json_config);
  getnRF(Feather).set_print_verbosity(Verbosity::V_HIGH);
    Feather.print_config();

    LPrintln("\n ** Setup Complete ** ");
}

void loop()
{
    if (getnRF(Feather).receive()) {
        Feather.display_data();
        getSD(Feather).log("nrf.csv");
    }

    Feather.pause();    // Pause according to 'interval' in config
                    // This controls the frequency of checking
                    // for incoming data

}
winniiew commented 3 years ago
"{\
    'general':\
    {\
        'name':'Device',\
        'instance':1,\
        'interval':100\
    },\
    'components':[\
        {\
            'name':'nRF',\
            'params':[120,01,1,0,3,200,1]\
        },\
        {\
            'name':'SD',\
            'params':[true,1000,10,'datafile',false]\
        }\
    ]\
}"
lukegoertzen commented 3 years ago

For reference, the RF24 library warnings are typical and aren't a concern.

The actual issue is that the compiled code is larger than can fit in flash (there's 256KB, so 1648 bytes is just barely over). The approach generally would be to disable some of the Internet/Sensors/Radios/Actuators/Max options, but you already have it as minimal as practical for this example (though you could disable sensors (it still leaves analog and digital enabled) for the sake of testing). I'm guessing changes to the library / addition of extra sensors would be why this combination no longer fits in flash.

A potential solution would be subdividing the menu options to enable subsets of radios or sensors, rather than all or nothing for both.

udellc commented 3 years ago

If we are unable to enable sensors and radio at the same time, then the way we subdivide the systems may be too small. I agree that we may want to be more specific about which radio, or which family of sensors if we cannot compile both without memory issues.

winniiew commented 3 years ago

Serial monitor output for Loom+receive

Initialized Serial!

= = = = = Parse Config = = = = =

Config Pretty Version:
{
  "general": {
    "name": "Device",
    "instance": 1,
    "interval": 100
  },
  "components": [
    {
      "name": "nRF",
      "params": [
        120,
        1,
        1,
        0,
        3,
        200,
        1
      ]
    },
    {
      "name": "SD",
      "params": "default"
    }
  ]
}
SIZE: 376
= = = = = Generate Objects = = = = =

[nRF] Setting nRF data rate to: 250 kbps
[nRF] Setting nRF power level to: Default
[Device] Adding Module: nRF
[SD] Initialize failed
[Device] Cannot add inactive module
= = = = = = = = = = = = = = = = =

[nRF] Set print verbosity to: High
[Device] Config:
    Device Name         : Device
    Instance Number     : 1
    Device Type         : Node
    Interval            : 100
[Device] Modules:
        [+] nRF

 ** Setup Complete ** 
[nRF] Receive failed
[nRF] Receive failed
[nRF] Receive failed
winniiew commented 3 years ago

Serial monitor output for Loom_transmit

[Device] Json:
{
  "type": "data",
  "id": {
    "name": "Device",
    "instance": 1
  },
  "contents": [
    {
      "module": "Packet",
      "data": {
        "Number": 9
      }
    },
    {
      "module": "Analog",
      "data": {
        "Vbat": 4.284522,
        "A[0]": 1901,
        "A[1]": 1555,
        "A[2]": 1595,
        "A[3]": 1400,
        "A[4]": 1663,
        "A[5]": 1794
      }
    }
  ]
}
[nRF] ⸮⸮type⸮data⸮id⸮⸮name⸮Device⸮instance⸮contents⸮⸮⸮module⸮Packet⸮data⸮⸮Number   ⸮⸮module⸮Analog⸮data⸮⸮Vbat⸮@⸮ͤA[0]⸮D⸮
MsgPack size: 167
[nRF] Broadcasted
lukegoertzen commented 3 years ago

Is this a concern about the msgpack serialization? If so, the odd looking output on the 3rd to last line is because msgpack is a binary serialization format (https://msgpack.org, used because it serializes smaller) rather than just minified (whitespace-removed) json. So that wouldn't be anomalous if the receiver is able parse/print it properly (I think the receive example just has the incoming packets pretty-printed).

winniiew commented 3 years ago

Is this a concern about the msgpack serialization? If so, the odd looking output on the 3rd to last line is because msgpack is a binary serialization format (https://msgpack.org, used because it serializes smaller) rather than just minified (whitespace-removed) json. So that wouldn't be anomalous if the receiver is able parse/print it properly (I think the receive example just has the incoming packets pretty-printed).

The issue is that sometimes the portion before setup complete won't print and you have to reset the Feather, and the SD initialization. Carter and I were testing the nRF last week and couldn't figure out why it was no receiving even though it said broadcasted for the transmit output

lukegoertzen commented 3 years ago

I'm not certain on that issue right now, but for clarification on broadcasting, 'broadcasting' does not have an acknowledgement from the receiver, so it can still say it broadcast successfully without it the packet being received (compared to 'send', which does use an acknowledgement from the receiver to verify receipt of the packet for the success message).

rcpeene commented 3 years ago

The issue seems to be with the sender, not the receiver. Within nRF::send_impl(), the call to network->write(), a function from the RF24Network dependency, appears to always return false. After doing more investigating, part of the problem seems to be that the third argument to network->write() must be less than 120 for proper sending to occur. Most message packs that Loom sends are greater than 120 in length.

However, even when ensuring that the message pack is less than 120 in length, the call to network->write() still fails for unknown reasons. As far as I can tell, the problem is not with Loom, but the dependency or the hardware, because the arguments provided to network->write() all appear to be valid.

rcpeene commented 3 years ago

Okay Problem part 2 has been discovered. The nRF PCBs require using a Feather M0 Proto rather than a different kind of Feather. With this solved, the only remaining challenge is the Message Packs being longer than 120. This might require some reimplementation of nRF or Commplats to fix.

lukegoertzen commented 3 years ago

This may already be fixed, as there is code to support sending messages multiple packets (more tested with LoRa). The CommPlat send Interface could probably be cleaned up, but the packet splitting behavior should be handled transparently already.

rcpeene commented 3 years ago

You may be right. So far though I have tried to get the packet splitting to work and it still seems it won't work. As far as I can tell, if Loom detects a message to be too long (greater than 252), it will break up the JSON and send individual component data as JSON objects. If this is indeed happening, even after splitting up the JSON and converting it to a message pack, it yields messages of around 167 to 169 in length, which is still too long.

lukegoertzen commented 3 years ago

Ah, good point - evidence of that being less tested with nRF. That 252 shouldn't be hardcoded in the comm plat, it should get it from the subclass so it splits the message accordingly.

udellc commented 3 years ago

Luke, please advise here for code change!

lukegoertzen commented 3 years ago

Suggestion is a CommPlat constant initialized by derived classes, this value could be used in place of the 252 hardcoded in the CommPlat class.

rcpeene commented 3 years ago

The problem was ultimately in the dependency. Within the dependencies > RF24Network > RF24Network_config.h, there is a constant which the documentation advises may be changed called MAX_PAYLOAD_LENGTH. In the older dependency version we were using, this value had to be a multiple of 24. After updating the dependency, this constraint doesn't appear to be present.

The dependency itself is capable of handling message fragmentation for messages that are too long. This fragmentation can be disabled by altering a config setting, but is enabled by default. This setting will break up messages that are longer than 120. However, even with fragmentation enabled, the dependency will fail to send messages longer than MAX_PAYLOAD_LENGTH, which, by default was 144.

Going into the dependency config and changing this value to 252 appeared nearly sufficient for solving the issues. I knew that Loom Communication Platforms automatically break up messages longer than 252. Therefore, Loom handles message splitting for messages longer than 252, and for message packets between 120 and 252, RF24Network handles splitting those messages. Messages shorter than 120 are transmitted whole.

The other change required to get this fully functional was an attribute of the nRF module in Loom. The nRF.max_message_length value, which is set from the nRF constructor was set to 120 by default. This value is used to allocate a message buffer used when sending messages. Changing this to 252 allows nRF to allocate a message buffer of 252, long enough to fit the max message length from the dependency config settings. To accommodate this change, when writing the config.h with nRF, the max_message_length parameter must be 252 or longer, but will not actually affect message sending process as long as it is larger than 252.

This means that the max_message_length parameter is pretty much useless, and probably should not even be a parameter which is settable from the config. That is a design choice for a different GitHub issue, though.