Creating an array with a converted float variable

Hello!

I am trying to place a float variable that has been painfully converted from a String, into an array, and then calling the array again so that I could retrieve the value.

Why am I going in such a roundabout way? well the hardware is a pain, and I could not think of any other way.

Hardware I am using is the M5Stack Core and the LoRa modules that are made for it. I have a pair of them so that they are able to talk to each other.

I can concur that the sending end has no issues, and it’s mostly on the receiving end. I am also uploading data on to thingspeak.

So far, I have noticed that I am constantly receiving 5 outputs, or at least, 5 lines of converted values. I tried pushing them into an array and extracting only the last as it is the relevant data but to no avail.

#include <M5Stack.h>
#include <M5LoRa.h>
#include "ThingSpeak.h"
#include "secrets.h"
#include <WiFi.h>

char ssid[] = SECRET_SSID;   // your network SSID (name) 
char pass[] = SECRET_PASS;   // your network password
int keyIndex = 0;            // your network key Index number (needed only for WEP)
WiFiClient  client;

unsigned long myChannelNumber = SECRET_CH_ID;
const char * myWriteAPIKey = SECRET_WRITE_APIKEY;

int number = 0;

String outgoing;              // outgoing message

byte msgCount = 0;            // count of outgoing messages
byte localAddress = 0xFF;     // address of this device
byte destination = 0xBB;      // destination to send to

long lastSendTime = 0;        // last send time
int interval = 1000;          // interval between sends

void setup() {

  Serial.begin(115200);  //Initialize serial

  WiFi.mode(WIFI_STA);   
  ThingSpeak.begin(client);  // Initialize ThingSpeak
  
  M5.begin();
  while (!Serial);

  Serial.println("LoRa Duplex B");

      // Connect or reconnect to WiFi
  /*if(WiFi.status() != WL_CONNECTED){
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(SECRET_SSID);
    while(WiFi.status() != WL_CONNECTED){
      WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network. Change this line if using open or WEP network
      Serial.print(".");
      delay(5000);     
    } 
    Serial.println("\nConnected.");
    M5.Lcd.clear(BLACK);
  }*/

  // override the default CS, reset, and IRQ pins (optional)
  LoRa.setPins();// set CS, reset, IRQ pin

  if (!LoRa.begin(433E6)) {             // initialize ratio at 915 MHz
    Serial.println("LoRa init failed. Check your connections.");
    while (true);                       // if failed, do nothing
  }

  Serial.println("LoRa init succeeded.");
}

void loop() {
  
  /*if (millis() - lastSendTime > interval) {
    String message = "Data Received";   // send a message
    sendMessage(message);
    Serial.println("Sending " + message);
    M5.Lcd.setTextColor(BLUE);
    M5.Lcd.println("Sending " + message);
    lastSendTime = millis();            // timestamp the message
    interval = random(1000) + 500;    // 2-3 seconds
  }*/

  // parse for a packet, and call onReceive with the result:
  onReceive(LoRa.parsePacket());

  if(M5.BtnA.wasPressed()){
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.clear(BLACK);
  }

  if(M5.BtnB.wasPressed()){
    reinit();
  }

  M5.update();
}

void reinit(){
  Serial.println("LoRa Duplex Reinitialization");

  // override the default CS, reset, and IRQ pins (optional)
  LoRa.setPins();// set CS, reset, IRQ pin

  if (!LoRa.begin(433E6)) {             // initialize ratio at 915 MHz
    Serial.println("LoRa init failed. Check your connections.");
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.setTextColor(RED);
    M5.Lcd.println("Init failed!!!");
    while (true);                       // if failed, do nothing
  }

  Serial.println("LoRa init succeeded.");
}

void sendMessage(String outgoing) {
  LoRa.beginPacket();                   // start packet
  LoRa.write(destination);              // add destination address
  LoRa.write(localAddress);             // add sender address
  LoRa.write(msgCount);                 // add message ID
  LoRa.write(outgoing.length());        // add payload length
  LoRa.print(outgoing);                 // add payload
  LoRa.endPacket();                     // finish packet and send it
  msgCount++;                           // increment message ID
}

void onReceive(int packetSize) {
  float tempflt;
  if (packetSize == 0) return;          // if there's no packet, return

  // read packet header bytes:
  int recipient = LoRa.read();          // recipient address
  byte sender = LoRa.read();            // sender address
  byte incomingMsgId = LoRa.read();     // incoming msg ID
  byte incomingLength = LoRa.read();    // incoming msg length

  String incoming = "";

  while (LoRa.available()) {
    incoming += (char)LoRa.read();
    M5.Lcd.setCursor(0,0);
    M5.Lcd.setTextColor(YELLOW, BLACK);
    M5.Lcd.setTextSize(2.5);
    M5.Lcd.printf("TMP Rcv: %f \r", tempflt);

    if (incomingLength == 5)
    {
      char icmgarray[incoming.length() + 1];
      incoming.toCharArray(icmgarray, sizeof(icmgarray));
      tempflt = atof(icmgarray);
      Serial.println(tempflt);
      //float tempfltarray[] = {tempflt};
      //Serial.println(tempfltarray[5]);
    }
    
      // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
  // pieces of information in a channel.  Here, we write to field 1.
  /*int x = ThingSpeak.writeField(myChannelNumber, 1, tempflt, myWriteAPIKey);
  if(x == 200){
    Serial.println("Channel update successful.");
    M5.Lcd.setCursor(0,50);
    M5.Lcd.setTextSize(2.0);
    M5.Lcd.printf("TMP Rcv2: %s \r", tempflt);
  }
  else{
    Serial.println("Problem updating channel. HTTP error code " + String(x));
  }
  delay(20000);*/
  }

  if (incomingLength != incoming.length()) {   // check length for error
    Serial.println("error: message length does not match length");
    return;                             // skip rest of function
  }

  // if the recipient isn't this device or broadcast,
  if (recipient != localAddress && recipient != 0xFF) {
    Serial.println("This message is not for me.");
    return;                             // skip rest of function
  }

  // if message is for this device, or broadcast, print details:
  /*Serial.println("Received from: 0x" + String(sender, HEX));
  Serial.println("Sent to: 0x" + String(recipient, HEX));
  Serial.println("Message ID: " + String(incomingMsgId));
  Serial.println("Message length: " + String(incomingLength));
  Serial.println("Message: " + incoming);
  Serial.println("RSSI: " + String(LoRa.packetRssi()));
  M5.Lcd.println("RSSI: " + String(LoRa.packetRssi()));
  Serial.println("Snr: " + String(LoRa.packetSnr()));
  Serial.println();

  /*M5.Lcd.setTextColor(YELLOW);
  M5.Lcd.println("Message: " + incoming);*/
 }

This is the whole code.

and this is the portion of the code that I am having the most trouble with.

oid onReceive(int packetSize) {
  float tempflt;
  if (packetSize == 0) return;          // if there's no packet, return

  // read packet header bytes:
  int recipient = LoRa.read();          // recipient address
  byte sender = LoRa.read();            // sender address
  byte incomingMsgId = LoRa.read();     // incoming msg ID
  byte incomingLength = LoRa.read();    // incoming msg length

  String incoming = "";

  while (LoRa.available()) {
    incoming += (char)LoRa.read();
    M5.Lcd.setCursor(0,0);
    M5.Lcd.setTextColor(YELLOW, BLACK);
    M5.Lcd.setTextSize(2.5);
    M5.Lcd.printf("TMP Rcv: %f \r", tempflt);

    if (incomingLength == 5)
    {
      char icmgarray[incoming.length() + 1];
      incoming.toCharArray(icmgarray, sizeof(icmgarray));
      tempflt = atof(icmgarray);
      Serial.println(tempflt);
      //float tempfltarray[] = {tempflt};
      //Serial.println(tempfltarray[5]);
    }
    
      // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
  // pieces of information in a channel.  Here, we write to field 1.
  /*int x = ThingSpeak.writeField(myChannelNumber, 1, tempflt, myWriteAPIKey);
  if(x == 200){
    Serial.println("Channel update successful.");
    M5.Lcd.setCursor(0,50);
    M5.Lcd.setTextSize(2.0);
    M5.Lcd.printf("TMP Rcv2: %s \r", tempflt);
  }
  else{
    Serial.println("Problem updating channel. HTTP error code " + String(x));
  }
  delay(20000);*/
  }

The image that I attached is the output I am currently getting through the Serial monitor.

If anyone has any ideas, please, do tell! I’m hitting a bottleneck and I am struggling. Thanks!

If you are determined to us a String then why not use the toFloat() function ?

Right. That would simplify the conversion process. the conversion still results in 5 values being printed. It seems like I would still have to throw them into an array so that I am able to isolate the data.

However, when I throw them into an array, and attempt to extract the data, the value results in a 0 or a random value.

Array's not my strong suit. Is it possible to dump variables into the array? If so, what is the method to do so? If not, how should I approach extracting the one value that I need?

Is it possible to dump variables into the array?

Of course, otherwise they would be useless.

Array’s not my strong suit

I suggest that you create a small example to play with
Put this in setup() in a simple sketch

Serial.begin(115200);  //choose your own baud rate
float anArray[3];  //array index is 0 to 2
anArray[0] = 123.45;
anArray[1] = 345.678;
anArray[2] = 999.999;
for (int x = 0; x < 3; x+=)
{
  Serial.println(anArray[x]);
}

UKHeliBob:

for (int x = 0; x < 3; x+=)

I seem to bump into an error with this specific line.

sketch_jan16a:12:32: error: expected primary-expression before ‘)’ token
for (int x = 0; x < 3; x+= )
^
exit status 1
expected primary-expression before ‘)’ token

As far as I know, doesnt the compound operator ‘+=’ require 2 variables? or at least to val? e.g x+=y

  for (int x = 0; x < 3; x+= )

Whoops on my part. It should, of course, be

 for (int x = 0; x < 3; x++ )

I blame my dodgy keyboard :slight_smile:

UKHeliBob:

  for (int x = 0; x < 3; x+= )

Whoops on my part. It should, of course, be

 for (int x = 0; x < 3; x++ )

I blame my dodgy keyboard

So I get how that array works, least those lines of codes.

If i would like to put variables in, how would I go about doing it?

Say

float tempflt;
tempflt = incoming.toFloat();

tempfltarray[4];

tempfltarray [0] = ???;
. 
.
.
.

my tempflt is a variable on its own. a variable that prints 5 lines. oh boy

If i would like to put variables in, how would I go about doing it?

tempfltarray[0] = someVariable;

What if someVariable has 5 values?

thenecniv:
What if someVariable has 5 values?

Declare the array to hold 5 values and put each of the 5 values in their own level, but remember that when the array levels are used they will be numbered from 0 to 4

thenecniv:
What if someVariable has 5 values?

Schrödinger's variable?

UKHeliBob:
Declare the array to hold 5 values and put each of the 5 values in their own level, but remember that when the array levels are used they will be numbered from 0 to 4

Almost certain that this is wrong (also, wasn't able to work on codes for abit)

      tempflt = incoming.toFloat();
      float tempfltarray[5];
      tempfltarray[0] = tempflt;
      tempfltarray[1] = tempflt;
      tempfltarray[2] = tempflt;
      tempfltarray[3] = tempflt;
      tempfltarray[4] = tempflt;
      tempfltupl = tempfltarray[4];
      Serial.println(tempfltupl);

well regardless, I'm still getting 5 lines of values on my serialprint

You are putting the same value in all 5 levels of the array. Why ?
Then you set a variable to the value of the last element in the array and print it. What is that all about ?

Please remind me what you are trying to do

Honestly I have no idea why I did that. I really have no clue.

Thing is, the variable that I am putting in, tempflt, has 5values attached to it, a single variable with 5 lines of values

I have declared my array as float, and I wondering if I could dump that one single variable into the array?

Would the array separate the values on its own?

a single variable with 5 lines of values

That sounds impossible.

Please provide an example and explain where the values come from

UKHeliBob:
That sounds impossible.

Please provide an example and explain where the values come from

With the screenshot I have provided (albeit does not show too clearly), the variable 'tempflt' as you know, is a converted variable from another variable, 'String incoming'.

By printing variable 'incoming', I will attain 5 outputs. Let's say that the temperature is 23.50 degrees.

First, I will get the number '2' as the first line, and then '23' as the second line, '23.' as the third, '23.5' as the fourth and finally the full '23.50' as the fifth line.

The original value of 23.50 is being split into 5 sections.

So don't do anything with the value received until it is complete

I have tried putting a buffer in the past, but I did not get the result that I wanted.

there is a portion of my code where it is able to detect incomingMessage Length, but obviously, the message length is correct, hence the data passes through, but all I could print out, were those 5 values.

Hence why I am trying to create an array to see if it will store those 5 values instead and extract the last data. I am running out of ideas to delay and wait till its final value, since I am unable to separate the 5 values in the first place.

You seem to know how many characters you will receive

  byte incomingLength = LoRa.read();    // incoming msg length

So read characters and add them to your String until you have them all then print the String

Report back when you have that working