Calling a function in another function

Hello all, I want to thank you guys for helping out so far. as of now I'm stuck on an issue when I don't know how to call a function in a different function. I am trying to call the "void app(uint8_t data)" function inside of my "static void prepareTxFrame( uint8_t port )" function in order to set up a type of sensitivity setting. The case switch part of the app function works properly and displays the different "Command" setting when data is sent. Also when I change the readingMin and readingMax global variables, the if statements in my "prepareTxFrame" function also perform how I want them to. I am just SUPER lost on how to call that "app" function in order to change the value of "Command". Does anyone have any suggestions that could point me in the right direction?

void app(uint8_t data)
{
  
  
  //lora_printf("data:%d\r\n", data);
  switch (data)
  {
    case 49:
      {
        Command = 1;
        Serial.println("Command 1");
        break;
      }
    case 50:
      {
        Command = 2;
        Serial.println("Command 2");
        break;
      }
    case 51:
      {
        Command = 3;
        Serial.println("Command 3");
        break;
      }
    case 52:
      {
        Command = 4;
        Serial.println("Command 4");
        //Serial.println(data);
        break;
      }
    default:
      {
        break;
      }
  }

}




void  downLinkDataHandle(McpsIndication_t *mcpsIndication)
{
  LoRa_data = "";
  lora_printf("+REV DATA:%s,RXSIZE %d,PORT %d\r\n", mcpsIndication->RxSlot ? "RXWIN2" : "RXWIN1", mcpsIndication->BufferSize, mcpsIndication->Port);
  lora_printf("+REV DATA:");
  app(mcpsIndication->Buffer[0]);

  for (uint8_t i = 0; i < mcpsIndication->BufferSize; i++)
  {
    lora_printf("%02X", mcpsIndication->Buffer[i]);
    LoRa_data = LoRa_data + (String)(char)mcpsIndication->Buffer[i];

  }
  lora_printf("\r\n");
  Serial.println(LoRa_data);
}

static void prepareTxFrame( uint8_t port )
{

  pinMode(Vext, OUTPUT);
  digitalWrite(Vext, LOW);
  float Voltage = value * 5.0 / 1023;
  float Percentage = map(Voltage, 3.6, 4.2, 0, 100);
  float Perc = ((Percentage * -1) / 3);
  int16_t Battery = (Perc + 0);
  float LatRead = gps.location.lat();
  float LonRead = gps.location.lng();
  float AltRead = gps.altitude.feet();
  uint16_t HourRead = gps.time.hour();
  uint16_t MinRead = gps.time.minute();
  uint16_t SecRead = gps.time.second();
  int16_t SensorRead = ads.getLastConversionResults();
  Serial.print(LoRa_data);
  //if LoRa_data = 
app((int)(&data));
  if (Command = 1) {
    readingMax = 25;
    readingMin = -25;
  }
  else if (Command = 2) {
    readingMax = 70;
    readingMin = -70;
  }
  else if (Command = 3) {
    readingMax = 150;
    readingMin = -150;
  }
  else if (Command = 4) {
    Serial.println("Success");
  }



  if (SensorRead > readingMax or SensorRead < readingMin )
  {

    digitalWrite(Vext, HIGH);
    unsigned char *puc;
    appDataSize = 22;
    appData[0] = (int8_t)(SensorRead >> 8);
    appData[1] = (int8_t)SensorRead;

    appData[2] = (int8_t)(Battery >> 8);
    appData[3] = (int8_t)Battery;

    appData[4] = (uint8_t)(HourRead >> 8);
    appData[5] = (uint8_t)HourRead;

    appData[6] = (uint8_t)(MinRead >> 8);
    appData[7] = (uint8_t)MinRead;

    appData[8] = (uint8_t)(SecRead >> 8);
    appData[9] = (uint8_t)SecRead;

    puc = (unsigned char *)(&LatRead);
    appData[10] = puc[0];
    appData[11] = puc[1];
    appData[12] = puc[2];
    appData[13] = puc[3];

    puc = (unsigned char *)(&LonRead);
    appData[14] = puc[0];
    appData[15] = puc[1];
    appData[16] = puc[2];
    appData[17] = puc[3];

    puc = (unsigned char *)(&AltRead);
    appData[18] = puc[0];
    appData[19] = puc[1];
    appData[20] = puc[2];
    appData[21] = puc[3];


    Serial.print("Lat=");
    Serial.print(LatRead);
    Serial.print(", Lon=");
    Serial.print(LonRead);
    Serial.print(", Alt=");
    Serial.println(AltRead);
    Serial.print("Time: ");
    Serial.print(HourRead);
    Serial.print(":");
    Serial.print(MinRead);
    Serial.print(":");
    Serial.println(SecRead);
    Serial.print("Voltage: ");
    Serial.print(Voltage);
    Serial.print(", Percentage: ");
    Serial.println(Perc);
    Serial.print("Sensor Reading: ");
    Serial.println(SensorRead);
  }

  else {
    digitalWrite(Vext, HIGH);
    unsigned char *puc;
    appDataSize = 2;

    appData[0] = (int8_t)(Battery >> 8);
    appData[1] = (int8_t)Battery;
  }
}

What have you tried, and what went wrong?

What is your intent with this line? It calls app() with the address of "data", while app() expects a number contained in a byte.
app((int)(&data));

You call it the same as you would anywhere else in the sketch but you must ensure that any data passed to the function is of the right data type

Honestly I was just trying things out, I tried to call that function like I have others in the past like this

app();

but I received an error message stating that " too few arguments to function 'void app(uint8_t)' "

When I attempted to call it with

app((int)(&data));

it was the only way I no longer got that error message

That usually doesn't work well.

app(49);
would be typical call, and that would set command to 1.

byte data=49;
app(data);

would be another possibility.

void app(uint8_t data)

The app() function takes a byte as a mandatory parameter so it is no wonder that calling it without a parameter causes an error

When you call it from within the prepareTxFrame() function then what do you want the app() function to do and what value needs to be passed to it in order for it to do what you want ?

so essentially this is a LoRa node that is receiving data. when I send the hexadecimal data it is then converted using the

void  downLinkDataHandle(McpsIndication_t *mcpsIndication)

and then for this library the app function uses the case switch to do something as a result from that downlinked data received. I am trying to use it to change the value of "Command" in order to uses that in an if statement. So I need the value of command to change depending on whet is sent. Ive been struggling on this for a while now.

I need the value of Command to change as the device receives data. The command value is what Im looking to get from the app function.

  if (Command = 1)

I am still not clear what you are doing but fix this (and others) before you do anything else

It sounds like you don't yet completely understand how to decode the LoRa message, so work on that.

You need to pass the app function a byte containing a value in the range 49 to 52, in order for it do do anything.

Note: 49-52 are the decimal values for ASCII characters '1' to '4', so that makes good sense. You could call
app('1');
to set command to 1.

Also make sure that you understand the difference between "=" and "==".

The LoRa message is decoded in the "void downLinkDataHandle(McpsIndication_t *mcpsIndication)"

for (uint8_t i = 0; i < mcpsIndication->BufferSize; i++)
  {
    lora_printf("%02X", mcpsIndication->Buffer[i]);
    LoRa_data = LoRa_data + (String)(char)mcpsIndication->Buffer[i];

  }
  lora_printf("\r\n");
  Serial.println(LoRa_data);

I can decode the message and save it into the string "LoRa_data"

this is a work around attempt because I don't know how to call that function either into the static "void prepareTxFrame( uint8_t port ) " other wise I would just set

String LoRa_data;
String Message = LoRa_data;

    if (Message.equals("level:1")) {
      readingMax = 150;
      readingMin = -150;
    }

I did something similar that worked in a node-to-node sketch a while ago but this library doesn't have the "LoRa.read" feature. so I'm trying to figure out another way.

Great, but what part of that message is actually relevant to your question?

The function app() understands exactly four values, communicated to it via one byte.

I'll do some more reading to better understand what I need to do.

Have you fixed the problem noted in post #9 ?

I did i changed it to == but still no luck.

My five cents:
your app(uint8_t data) takes one byte as argument.
Trying to call via app((int)(&data)); is completely "wrong":
You paste the address of a memory data (as 32bit address), even you convert to (int) - it is truncated down (behind the scene) to an uint8_t (you take just the lowest byte of the data address, but not any character from a buffer).

I do not know where exactly your problem is (besides to get it "compile-clean").
I would mention this:
you might deal with an INT driven system, or with RTOS. For instance, your LORA functions could run in background and keep going to receive data.
But when you use a buffer - provided by LORA functions, e.g. your LoRa_data = LoRa_data + (String)(char)mcpsIndication->Buffer[i]; - it might be possible that this Buffer is overwritten, updated. For instance: another LORA message comes in and uses the same buffer. It overwrites the Buffer which you try still to "copy".

I guess: when it comes to "parallel actions" (threads, even an INT is such one), and you use a buffer - the buffer is potentially "shared". It can be overwritten when you use.

I do not know if this the issue for you.
There is nothing wrong with calling app(uint8_t data) as a function as long it is a single byte.
Just to keep an eye on "race conditions", e.g. the buffer where you take this byte from has been changed meanwhile (something received). You might be "surprised" why it is not the value you would expect to see.

A few comments after I scanned the code

A) It seems to be that the 'data' argument is actually character; checking for 49 is the same as checking for character '1', and then setting Command to integer 1. Maybe change case 49: to case '1': etc. Maybe also change signature to void app(char data)

B) I advise against changing a global variable (Command) inside the app function, especially as it is effectively just a mapping function. More readable IMNSHO is to return the value that Command is to become - or just use a local variable. So the signature becomes int app(uint8_t data) or int app(char data). This assumes that it's defined as int Command; I didn't see it.

C) A couple of times (in switch and if .. else if constructs) you silently ignore incorrect values. I advise adding something like

 Serial.print("Unexpected value of x");
 Serial.print(data, HEX); // or Command or ...
 Serial.print(" @ ");
 Serial.println(__LINE__, DEC);

D) If RAM memory usage starts to become a problem, consider changing things like

 Serial.print("Unexpected value of x");

to

 Serial.print(F("Unexpected value of x"));

which reads the strings from Flash (where they are stored anyway) rather than taking up RAM space.

HTH

Yes: you mix characters as integers and "ASCII code".
A '1' - as ASCII code - is hex 0x31 or decimal 49.
You cannot use 1 just for assuming it is an ASCII character (which has value 49).
A character (char) for the compiler is just an 8bit value, any value 0..255.

But you can do switch like this:

switch (data) {
  case 1 :  //this is really binary value 1, not ASCII character for '1'
  case '1' : //this checks for ASCII character '1' (value d'49)
  case 49 : //this is the same as '1'! you get error due to same case value
  case 0x31 : // this is also the same as '1'! you get also compile error
                           //an ASCII '1' is 0x31 or 49 (d'49), all the same value

So, distinguish between real values (0, 1, 2, ...) and ASCII characters ('0', '1', '2').
ASCII characters have also real values, but encoded ('0' = 0x30, '1' = 0x31, ... 'A' = 0x41, 'B' - 0x42). Your compiler does not know anything about "ASCII characters", except:
You use "ASCII-encoding", e.g.:

uint8_t c = '1';    //you assign a binary value 0x31 to it!

There is not a type for 'ASCII characters': all is char (a byte, 8bit). MCU does not care if it is an ASCII character or a byte value (both are identical). You had to know if you mean an ASCII-character '1' or the value 1 ('1' is 0x31, d'49 as value).

uint8_t (unsigned char) and char of same size (8bit): the uint8_t defines as "always" positive (never a sign bit), where char is an 8bit signed value (with a sign bit).

If you assign a char or uint8_t (unsigned char) to an int: the compiler will do for you the conversion: from an 8bit to an 16bit or even 32bit value. No complains by compiler - it can extend 8bit to larger number of bits. There is a type-conversion behind the scene.
Just the opposite could fail with an error message: char t = (int)0x1234; will truncate (it discards the MSB byte), and compiler will "warn" you.

"incorrect values":
There is this

    default: //all other values not defined as case

statement, which handlers all other cases. switch(val) is pretty "cool": if is faster as any if-else-if-else (it uses a table with entries to jump directly depending on val). And it much cleaner code.
Sometime the problem if you have a "fall-through": some compilers generate a warning, even it is intentional to fall through: you want to do the same code as you do with another one.
I think there is a #pragma to deal with it (tell compiler it is your intention to have "fall-throug").

switch (val) {
    case : 1
    case : 2 //do the same stuff for 1 and 2 ("fall-through")
               break;
    default: //anything else, unexpected value

To forget a break can be really serious: worst case: you forget the break on the case right before default: you would execute the default code even for this valid case condition.

Using this "F" (I think, it is Arduino-specific, for some specific boards, usually I do not use such one, e.g. on STM32 boards, Portenta H7) - yes: it tells the compiler:
"place the string we want to print on Flash memory (Read-Only, RO, memory). It saves the space in RAM. Potentially w/o the F - all your strings are on RAM and they "eat up the RAM" space.

Great job. I think you will figure out "what happens" if you keep "thinking" about "what is this code doing?" (even behind the scenes, e.g. implicit (hidden) type conversion, placing data on ROM vs. RAM, what is ASCII-code ...)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.