Sending two or more different sensor values independently

Hi all,
I am trying to send two independent sensor values over LoRa. I am using TTGO board (ESP32 with LoRa chip). I am using LDR sensor that measures light intensity and Ping (Range) sensor. When I wrote the code, only one value appears at M2X server (The value from LDR sensor). Inside the code, I used the following two lines to send data to through the TTGO board:

LMIC_setTxData2(1, mydata1, sizeof(mydata1), 0);
LMIC_setTxData2(1, mydata2, sizeof(mydata2), 0);

It seems that the LMIC_setTxData2 takes the reading from mydata2 and send it to LoRa Chip.

What I need is: Sending the value of LDR sensor first and after 10 seconds I want to send the value of the Ping sensor.

The full code is below for your reference. Your contributions are very much appreciated.

Thanks in advance.

Click here to see my code

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include <U8x8lib.h>

int Trig=12;
int Echo=13;
int LDR = 34;
int LightIntensity = 0;

const lmic_pinmap lmic_pins = { .nss = 18,
.rxtx = LMIC_UNUSED_PIN,
.rst = 14,
.dio = {26, 33, 32},};

U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8( 15, 4, 16);
static const u1_t PROGMEM APPEUI[8]= { 0x00, 0x80, 0x00, 0x00, 0xA0, 0x00, 0x1F, 0x18 };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
static const u1_t PROGMEM DEVEUI[8]={ 0x11, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22 };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
static const u1_t PROGMEM APPKEY[16] = { 0x00, 0x80, 0x00, 0x00, 0xA0, 0x00, 0x1F, 0x18, 0x00, 0x80, 0x00, 0x00, 0xA0, 0x00, 0x1F, 0x18 };
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}

const unsigned TX_INTERVAL = 20;

static osjob_t sendjob;
void onEvent (ev_t ev) {
switch (ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F(“Scan Timeout”));
u8x8.drawString(0, 4, “Scan Timeout”);
break;
case EV_BEACON_FOUND:
Serial.println(F(“Beacon Found”));
u8x8.drawString(0, 4, “Beacon Found”);
break;
case EV_BEACON_MISSED:
Serial.println(F(“Beacon Missed”));
u8x8.drawString(0, 4, “Beacon Missed”);
break;
case EV_BEACON_TRACKED:
Serial.println(F(“Beacon Tracked”));
u8x8.drawString(0, 7, “Beacon Tracked”);
break;
case EV_JOINING:
Serial.println(F(“Joining…”));
u8x8.drawString(0, 4, “Joining…”);
break;
case EV_JOINED:
Serial.println(F(“Joined!”));
u8x8.drawString(5, 4, "Joined! ");
LMIC_setLinkCheckMode(0);
break;
case EV_RFU1:
Serial.println(F(“RFU1”));
u8x8.drawString(0, 4, “RFU1”);
break;
case EV_JOIN_FAILED:
Serial.println(F(“Join Failed”));
u8x8.drawString(0, 4, “Join Failed”);
break;
case EV_REJOIN_FAILED:
Serial.println(F(“Rejoin Failed”));
u8x8.drawString(0, 4, “Rejoin Failed”);
break;
case EV_TXCOMPLETE:
Serial.println(F(“TX Complete”));
u8x8.drawString(0, 4, “TX Complete”);
if (LMIC.txrxFlags & TXRX_ACK) { Serial.println(F(“Received ACK”));
u8x8.drawString(0, 5, “Received ACK”);
}
if (LMIC.dataLen) { Serial.println(F(“Received “));
u8x8.drawString(0, 3, “RX “);
Serial.println(LMIC.dataLen);
u8x8.setCursor(4, 3);
u8x8.printf(”%i bytes”, LMIC.dataLen);
Serial.println(F(” bytes of payload”));
u8x8.setCursor(0, 5);
u8x8.printf(“RSSI %d SNR %.1d”, LMIC.rssi, LMIC.snr); }
os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F(“Lost SYNC”));
u8x8.drawString(0, 4, “Lost SYNC”);
break;
case EV_RESET:
Serial.println(F(“Reset”));
u8x8.drawString(0, 4, “Reset”);
break;
case EV_RXCOMPLETE:
Serial.println(F(“RX Complete”));
u8x8.drawString(0, 5, “RX Complete”);
break;
case EV_LINK_DEAD:
Serial.println(F(“Link Dead”));
u8x8.drawString(0, 4, “Link Dead”);
break;
case EV_LINK_ALIVE:
Serial.println(F(“Link Alive”));
u8x8.drawString(0, 5, “Link Alive”);
break;
default:
Serial.println(F(“Unknown event”));
u8x8.setCursor(0, 4);
u8x8.printf(“Unknown Event %d”, ev);
break; }}

void do_send(osjob_t* j) {

int dur;
long dis;
int intensity = 0;

static uint8_t mydata1[] = { 0,0,0,0,0,0,0,0};
static uint8_t mydata2[] = { 0,0,0,0,0,0,0,0};

digitalWrite(Trig,LOW);
delayMicroseconds(2);
digitalWrite(Trig,HIGH);
delayMicroseconds(10);
digitalWrite(Trig,LOW);
dur=pulseIn(Echo,HIGH);
dur = dur / 29 / 2;

dtostrf(dur, 5, 2, (char*)mydata1);

Serial.print(“Water Level = “);
Serial.print(dur);
Serial.println(” cm”);

intensity = analogRead(LDR);
Serial.print("Light intensity = ");
Serial.println(intensity);
dtostrf(intensity, 5, 2, (char*)mydata2);

LMIC_setTxData2(1, mydata1, sizeof(mydata1), 0);
LMIC_setTxData2(1, mydata2, sizeof(mydata2), 0);

}

void setup() {
Serial.begin(115200);
pinMode(Trig,OUTPUT);
pinMode(Echo,INPUT);

u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.drawString(5, 1, “Node 5”);
u8x8.drawString(0, 2, “Level & Intensit”);
SPI.begin(5, 19, 27);
os_init();
LMIC_reset();
do_send(&sendjob);

}
void loop() {
os_runloop_once();
}

For sake of efficiency, you really should combine both readings in the same packet (ie, same call to setTxData2), even if one ends up a few seconds “stale”.

The overhead for a packet is fixed regardless of contents, and with only one reading you probably have more overhead than application payload, which is inefficient even in a private system and in a shared one will quickly cause you to consume more than your share of airtime.

Either use memcpy() to move them into the same buffer, or define your packet as a struct and assign the constituent values.

If you really wanted to transmit them independently, do something like put each data type on its own port. But please, please don’t be wasteful like that.

Thank you for your prompt reply. I totally agree with you that the second solution is wasteful.

I am not that good in coding. Could you please help me out with memcpy() instruction and how to implement it inside my code?

First, you should be sending binary data, not strings, so probably something like

struct {
    double value1;
    double value2;
} tx_buff;

tx_buff.value1 = something;
tx_buff.value2 = something;

LMIC_setTxData2(1, (void *)tx_buff, sizeof(tx_buff));

And then you need to build a decoder that can parse these doubles.

It would be even better if you could use a single-precision float instead of a double.

Unfortunately, I tried this option and it did not work. It shows something about data conversion by LMIC_setTxData1 command.
It seems that option 2 is what can solve this issue with my modest coding ability. The period between two consecutive transmissions is 30 minutes.
So will you please guide me to transmit the two values independently.
Thanks

The first approach works, you just need to find and resolve the specific issue.

“It shows something about” is not a meaningful way to report a problem.

1 Like

The above is the syntax you used.

cslorabox showed you the correct way of doing this but is missing the final flag. Instead of this:
LMIC_setTxData2(1, (void )tx_buff, sizeof(tx_buff));

do this:
LMIC_setTxData2(1, (void )tx_buff, sizeof(tx_buff),0)

I did this already. I added the zero at the end.
When I run the code, I got this error:

In function ‘void do_send(osjob_t*)’:

TRY:143:28: error: invalid cast from type ‘do_send(osjob_t*)::’ to type ‘void*’

LMIC_setTxData2(1, (void *)tx_buff, sizeof(tx_buff),0);

                        ^

exit status 1
invalid cast from type ‘do_send(osjob_t*)::’ to type ‘void*’

I wrote the following:
struct {
double value1;
double value2;
} tx_buff;

tx_buff.value1 = dur; //This is the readings from the LDR sensor
tx_buff.value2 = intensity; //This is the reading from Ping sensor
LMIC_setTxData2(1, (void *)tx_buff, sizeof(tx_buff),0);

Try this:
LMIC_setTxData2(1, (uint8_t*)tx_buff, sizeof(tx_buff),0);

Here is the error message I got:

In function ‘void do_send(osjob_t*)’:

TRY:144:30: error: invalid cast from type ‘do_send(osjob_t*)::’ to type ‘uint8_t* {aka unsigned char*}’

LMIC_setTxData2(1, (uint8_t*)tx_buff, sizeof(tx_buff),0);
exit status 1
invalid cast from type ‘do_send(osjob_t*)::’ to type ‘uint8_t* {aka unsigned char*}’

You’ve go the definition of tx_buff somehow mixed up with the definition of the function do_send(), such that it thinks that tx_buff is a function.

Just an extra note: in your code both values are int. You should know that int type takes 2 bytes, so if you are not able to manage structs, just take byte values from the two ints and put them in the mydata buffer. Here some educational material: https://www.thethingsnetwork.org/docs/devices/bytes.html
Possibly sending them together as suggested, also because not always you will be able to send two packets with 10s interval between them.
If you really want to send them independently, of course all the code should be revised because you have to arrange two different deliveries, which is not just setting the data buffer. If you have modest coding ability, do not complicate your life (or hire a programmer :wink: ).

thanks for the advice. I will keep trying. If I give up, I will hire someone to educate me.