StuartsProjects / SX12XX-LoRa

Library for SX12XX LoRa devices
303 stars 66 forks source link

Read Partial Structure #57

Closed floatAsNeeded closed 1 year ago

floatAsNeeded commented 1 year ago

First of all thanks for sharing the library! Very good work.

Is not really an issue, but is there a way to read a part of the structure first and if it matches then read it all?

Thanks in advance!

StuartsProjects commented 1 year ago

No idea what you mean by 'the structure'

floatAsNeeded commented 1 year ago

Thanks for your reply!

Sorry, I expressed my sentence wrong. And actually looking at the code better I think it's already kind of there what I'm asking.

For example, you got a struct like this one

struct trackerPacket
{
  uint8_t trackerID[13];
  uint32_t txcount;
  float latitude;
  float longitude;
  uint16_t altitude;
  uint8_t satellites;
  uint16_t voltage;
  int8_t temperature;
};

You don't actually read the complete structure straight away, but you also check that the first part of the structure ( uint8_t trackerID[13]; ) is matching with the receiver by doing like this

RXPacketL = LT.receive( (uint8_t *) &location1, sizeof(location1), 0, WAIT_RX); //wait for a packet to arrive with no timeout

Am I right? Because that's very useful if you want to send different types of struct to the receiver that may have the same size but different data inside

I still need to test the library with some modules, but I mainly will use it for my project LoRa node to node and not LoraWan, but I see with your library you can set many types of settings with the module. I was using the EBYTE UART modules successfully but the problem is that is very hard to know the time on air of my message without the possibility of setting bandwidth and other values. So I was thinking of using your library with different modules. What kind of modules did you test with the library? I mean like manufacture modules that use the Semtech chip.

I also had another question: You mention that "There are library functions that use the millis() and micros() functions."

What type of functions use millis and micros? Because I'm actually using an Atmega328P but with an external crystal 32.768kHz and so my microcontroller it's actually off and power down with timer1 off all the time and just runs on the external crystal and timer2 to keep the time accurate because by using watch dogs it's not a good idea to keep time. So millis and micros won't work in my Atmega

StuartsProjects commented 1 year ago

As long as the structures used by the transmitter and receiver have the same types of data and in the same sequence then you can read the data out in any order.

An easier approach might be to write and read direct to\from the LoRa devices internal buffer as in the low memory examples.

The library should work with most all of the SPI based LoRa modules.

StuartsProjects commented 1 year ago

"What type of functions use millis and micros?"

Search the library file *.cpp for the use of millis() and micros().

millis() is mainly used for TX and RX timeouts, when set.

floatAsNeeded commented 1 year ago

I had a look at the low memory example, yeah I could use that as well.

Because I also need to send a few different structures with the same device to the receiver, that's why sometimes I need to know the start of the structure because maybe the total structure it's the same size as another one, but the data is different, so by changing the initial ID I can detect which structure is sent.

Thanks for pointing out that, I let you waste time :D

I see in the cpp it's also used for the reliable way to send the data and also as you said for the timeout, so should be fine for my use, although very interesting the reliable method of sending and receiving. To save power my atmega wakes up every second on timer 2 interrupt, so no millis.

StuartsProjects commented 1 year ago

No library issues

floatAsNeeded commented 1 year ago

Hi Stuart,

Just posting another question here regarding the library (not a library issue so no point in opening an issue)

In my project, I've some sensor data from different devices that transmit in a specific period of time set, because I know obviously the LoRa module can just receive one message at a time so what I used to do with the Ebyte modules, using an Ebyte library, is to first receive just a part of the message as identification if the data came from the device I wanted and then read the rest of the message.

I was looking at your example 18_Sensor_Receiver.ino that it checks that the data comes from the device we want that it's very useful.

I was wondering if when reading the packet received I could possibly do something like this:

void packet_Received_OK()
{
  //a LoRa packet has been received, which has passed the internal LoRa checks, including CRC, but it could be from
  //an unknown source, so we need to check that its actually a sensor packet we are expecting, and has valid sensor data

  uint8_t len;
  uint8_t contenterrors;                 //keep a count of errors found in packet

  RXpacketCount++;
  Serial.print(RXpacketCount);
  Serial.print(F(",PacketsReceived,"));

  LT.startReadSXBuffer(0);

  RXPacketType = LT.readUint8();           //the packet type received
  RXDestination = LT.readUint8();          //the destination address the packet was sent to
  RXSource = LT.readUint8();               //the source address, where the packet came from

  if  (RXPacketType == Sensor1)
  {
    /************************************************************************
      Highlighted section - this is where the actual sensor data is read from
      the packet
    ************************************************************************/
    temperature = LT.readFloat();             //the BME280 temperature value
    pressure = LT.readFloat();                //the BME280 pressure value
    humidity = LT.readUint16();               //the BME280 humididty value
    voltage = LT.readUint16();                //the battery voltage value
    statusbyte = LT.readUint8();              //a status byte, not currently used
    /************************************************************************/

    len = LT.endReadSXBuffer();

    printreceptionDetails();                   //print details of reception, RSSI etc
    Serial.println();

    contenterrors = checkPacketValid(len);     //pass length of packet to check routine

    if (contenterrors == 0)
    {
      Serial.println(F("  Packet is good"));
      ValidPackets++;
      printSensorValues();                     //print the sensor values
      Serial.println();
      printPacketCounts();                     //print count of valid packets and errors
      displayscreen1();
      Serial.println();
    }
    else
    {
      Serial.println(F("  Packet is not valid"));
      RXpacketErrors++;
      disp.clearLine(7);
      disp.setCursor(0, 7);
      disp.print(F("Errors "));
      disp.print(RXpacketErrors);
    }
  }
  else if (RXPacketType == Sensor2) {
    /************************************************************************
      Highlighted section - this is where the actual sensor data is read from
      the packet
    ************************************************************************/
    Light = LT.readFloat();             //the BME280 temperature value
    SolarRadiation = LT.readFloat();                //the BME280 pressure value
    Wind = LT.readFloat();               //the BME280 humididty value
    voltage = LT.readUint16();                //the battery voltage value
    statusbyte = LT.readUint8();              //a status byte, not currently used
    /************************************************************************/

    len = LT.endReadSXBuffer();

    printreceptionDetails();                   //print details of reception, RSSI etc
    Serial.println();

    contenterrors = checkPacketValid(len);     //pass length of packet to check routine

    if (contenterrors == 0)
    {
      Serial.println(F("  Packet is good"));
      ValidPackets++;
      printSensorValues();                     //print the sensor values
      Serial.println();
      printPacketCounts();                     //print count of valid packets and errors
      displayscreen1();
      Serial.println();
    }
    else
    {
      Serial.println(F("  Packet is not valid"));
      RXpacketErrors++;
      disp.clearLine(7);
      disp.setCursor(0, 7);
      disp.print(F("Errors "));
      disp.print(RXpacketErrors);
    }
  }
}

Thank you for your time and the great library and resources!

floatAsNeeded commented 1 year ago

I was just looking at the examples and I found one of them that could be also used for my case:

25_GPS_Tracker_Receiver_With_Display_and_GPS.ino

It's a different approach than what I was thinking on my previous post! Just waiting for my modules to arrive to test everything out.