Fram.write with float variable

I am experimenting with FRAM and I can't find out how to write float variables. I am using fram.write32(addrLoc, myData.humid); to write the variable and using humid=fram.read32(readLoc);,

myData.humid is a floating point variable but when I read it back, the decimal values are gone.

I suspect that the comand fram.write32 is writing a uint32_t, or long integer variable and so the decimals are removed.

I've gone through the examples but I can't find the syntax to wright a float.

Does anybody know the correct syntax to write a float?

The full sketch is below.

#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "FRAM.h"

FRAM fram;

#define I2C_SDA 33
#define I2C_SCL 32
//LiquidCrystal_I2C lcd(0x27, 20, 4); 
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


// Structure example to receive data
// Must match the sender structure
typedef struct struct_Data {
  char unit[8];
  char timeStamp[32];
  float humid;
  float temperature;
  float pressure;
  float battVolt;
} struct_Data;

// Create a struct_message called myData
struct_Data myData;

int counter;
int counter2;
float pressure_hold[16];
bool press=0;

const unsigned long startAddr=1000;
unsigned long addrLoc=startAddr;
unsigned long readLoc;
const uint8_t IndexLoc = 100;

bool output = 0;
// callback function that will be executed when data is received
void OnDataRecv(const esp_now_recv_info_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  
  Serial.println();
  Serial.println(myData.unit);
  char str[8];
  strcpy(str, myData.unit);
  fram.write(addrLoc, (uint8_t *)str, 8);
  addrLoc+=8;

  Serial.println(myData.timeStamp);
  char str2[32];
  strcpy(str2, myData.timeStamp);
  fram.write(addrLoc, (uint8_t *)str2, 32);
  addrLoc+=32;


  Serial.println(myData.humid);
  fram.write32(addrLoc, myData.humid);
  addrLoc+=4;

  Serial.println(myData.temperature);
  fram.write32(addrLoc, myData.temperature);
  addrLoc+=4;

  Serial.println(myData.pressure);
  fram.write32(addrLoc, myData.pressure);
  addrLoc+=4;

  Serial.println(myData.battVolt);
  fram.write32(addrLoc, myData.battVolt);
  addrLoc+=4;
  fram.write32(IndexLoc, addrLoc);
  Serial.print("addrLoc = ");
  Serial.println(addrLoc);

  Serial.print( "Number of records = ");
  int x=(addrLoc-startAddr)/56;
  Serial.println( x);
  

    Serial.println(counter);
    pressure_hold[counter]=myData.pressure;
    
    /*if(press){
      lcd.setCursor(7, 1);
      float meanPressure = arrayAverage(pressure_hold, 12);

      Serial.println(meanPressure);
      if(myData.pressure>meanPressure)
      {
        lcd.print("+");
      }
      else{
        lcd.print("-");
      }
    }
    counter++;
    if (counter>=15)
    {
      counter = 0;
      press=1;
    }*/



  output = 1;
  
}
 
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  Wire.begin(I2C_SDA, I2C_SCL);
  //fram.begin(0x50);
  fram.begin(0x7C);
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
 
  //fram.write32(IndexLoc, startAddr);///set initial index point
  //while(1)
  addrLoc=fram.read32(IndexLoc);
  Serial.print("addrLoc =");
  Serial.println(addrLoc);

  Serial.print( "Number of records = ");
  int x=(addrLoc-startAddr)/56;
  Serial.println( x);
  

  display.clearDisplay();
  //lcd.init();  // initialize the lcd
  //lcd.backlight();
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_register_recv_cb(OnDataRecv);
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.clearDisplay();
  display.display();
}
 
void loop() {
    allOutput();
    delay(5000);

    display.setTextSize(2); // Draw 2X-scale text    
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println(F("H "));
    display.setTextSize(4);
    display.println(myData.humid,1);
    display.setTextSize(2);
    display.println("%");
    display.display();
    delay(5000);

    display.clearDisplay();
    display.setCursor(0, 0);
    display.println(F("T "));
    display.setTextSize(4);
    display.println(myData.temperature,1);
    display.setTextSize(2);
    display.println(" C");
    display.display();
    delay(5000);

    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("V ");
    display.setTextSize(4);
    display.println(myData.battVolt,2);
    display.display();
    delay(5000);
  
    if(output){readFram();output=0;}
  

}

///////////////////////////////////////////////////////////
float arrayAverage(float variable[], int count) 
{
  float num = 0;
  for (int i = 0; i <= count - 1; i++) 
  {
    num = num + variable[i];  // Calculate sum of all array values
  }
  float average = float(num / count);
  return average;
}

void allOutput(){
  display.setTextSize(2); // Draw 2X-scale text
    display.setTextColor(SSD1306_WHITE);
    display.clearDisplay();
    display.setCursor(0, 0);
    display.print(F("H "));
    display.print(myData.humid,1);
    display.println("%");
    display.print(F("T "));
    display.print(myData.temperature,1);
    display.println(" C"); 
    display.print("P ");
    display.println(myData.pressure,0);
    display.print("V ");
    display.print(myData.battVolt,2);
    display.display();
}

void readFram()
{
  readLoc=startAddr;
  char str[8];
  char str2[32];
  float humid;
  float temperature;
  float pressure;
  float battVolt;


  
  Serial.println();
  while(readLoc<=addrLoc){
  
    
    fram.read(readLoc, (uint8_t *)str, 8);
    Serial.print(str);Serial.print(" ");
    readLoc+=8;

    
    
    
    fram.read(readLoc, (uint8_t *)str2, 32);
    Serial.print(str2);Serial.print(" ");
    readLoc+=32;


    
    humid=fram.read32(readLoc);
    //fram.readObject(readLoc, humid);
    Serial.print(humid);Serial.print(" ");
    readLoc+=4;

    temperature=fram.read32(readLoc);
    //fram.readObject(readLoc, temperature);
    Serial.print(temperature);Serial.print(" ");
    readLoc+=4;

    pressure=fram.read32(readLoc);
    //fram.readObject(readLoc, pressure);
    Serial.print(pressure);Serial.print(" ");
    readLoc+=4;

    battVolt=fram.read32(readLoc);
    //fram.readObject(readLoc, battVolt);
    Serial.println(battVolt);Serial.print(" ");
    readLoc+=4;
  }

  Serial.print( "Number of records = ");
  int x=(readLoc-startAddr)/56;
  Serial.println( x);

  
  
}

Please post a GitHub pointer to that particular Fram library.

The library is here.

Makes no sense. Floats aren't coded that way. Treating a float as an int doesn't magically strip the decimal point.

But, why didn't you try writeFloat() and readFloat()?

No, the cause of the issue is different.
Do you see at the library code?
The return value of the read32() method is.... uint32_t

uint32_t FRAM::read32(uint16_t memAddr)

I should have tried that it works.

Thanks, I am now sat here slapping my forhead.

I haven't delved into the library code. Library code is a bit beyond me at the moment.

Many of arduino libraries are written by the users - as well as FRAM_I2C library. Most of them don't have a detailed documentation, only a short Readme. The only way to learn how to use the library - read the methods and parameters in the source code.

In this case all you have to do is look at the function prototypes in the header file (Fram.h):

This obviously writes a 32-bit unsigned integer type:

  void     write32(uint16_t memAddr, uint32_t value);

And this obviously writes a float:

  void     writeFloat(uint16_t memAddr, float value);

If you want to write the entire struct, use:

  void     write(uint16_t memAddr, uint8_t * obj, uint16_t size);

Of course, there's are corresponding "read" function for each of the "write" functions.

The readme on the Github page pointed to is also illustrative.

1 Like

I need to start looking at library files again. I tried this when I first started using an arduino and it was all just gibberish to me and I assumed that they took a lot of experience to understand them. Some of them though I have now found are quite informative, and almost gobbledygook free.

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