Save after power off

Hi.
I have the code for a spirit level, it works fine but each time I either reset or power off, I have to use the calibration button to set level. If not the sensor just goes back to it’s original (wrong) position.

What I would like to add to the code is that after I have used the calibration button, the level is set, so next time I hit reset or power off then on, it will revert to the last level calibration I set with the button.

I am very new to this so please go easy on me! I don’t know if the value can be stored to the Epsom? ?

I am using a Nano.

Thanks

#include <Wire.h>
#include <ADXL345.h>

#define cs   10 // Arduino-Pin an Display CS   
#define dc   9  // Arduino-Pin an Display A0
#define rst  8  // Arduino Reset-Pin

#include "Adafruit_GFX.h"    // Adafruit Grafik-Bibliothek
#include "Adafruit_ST7735.h" // Adafruit ST7735-Bibliothek
#include <SPI.h>

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);  // Display-Bibliothek Setup


ADXL345 accel;

#define button_correction 3

void setup(void){

  Serial.begin(9600);

  pinMode(button_correction, INPUT);

  // Sensor
  accel.begin();        // Sensor initialisieren
  accel.setRange(accel.RANGE_16G);  // Empfindlichkeit einstellen
  
  // Display
  tft.initR(INITR_BLACKTAB);    // ST7735-Chip initialisieren
  tft.setTextWrap(true); 
  
  display_show();
}

const float alpha = 0.5;
double fXg = 0;
double fYg = 0;
double fZg = 0;

double x_correction=0;
double y_correction=0;

int x_value=0;
int y_value=0;
int old_x_value=1;
int old_y_value=1;

#define filter_count_max 40
byte filter_count=0;

#define correction_precision 300  // Sollte Anzeige im Liegen wackeln Wert vermindern

void loop(void){
 
  double pitch, roll, Xg, Yg, Zg;
  accel.read(&Xg, &Yg, &Zg);
  
  fXg+=Xg;
  fYg+=Yg;
  filter_count++;
  
  if(filter_count==filter_count_max-1){
  
    fXg/=filter_count_max;
    fYg/=filter_count_max;

    if(digitalRead(button_correction)==HIGH){
      x_correction=fXg; 
      y_correction=fYg;
    }
    
    x_value=(fXg-x_correction)*correction_precision;
    y_value=(fYg-y_correction)*correction_precision;

    //display_info();
    display_graphic();
    
    old_x_value=x_value;
    old_y_value=y_value;
    
    fXg=0;
    fYg=0;
    filter_count=0;
  }
  
  delay(5);

}

#define hx 27
#define hy 16
#define hw 95
#define hh 18
#define hb 7

#define vx 5
#define vy 38
#define vw 18
#define vh 95
#define vb 7

#define cx 75
#define cy 86
#define cr 45
#define cb 5

void display_show(){

  tft.fillScreen(ST7735_BLACK); 
  
  set_text(32,3,"Wasserwaage",ST7735_BLUE,1);  
  set_text(14,149,"blog.simtronyx.de",ST7735_GREEN,1);
  
  tft.drawRect(hx-1,hy-1,hw+2,hh+2,rgb565(128,128,128));
  tft.drawRect(hx+1,hy+1,hw-2,hh-2,rgb565(128,128,128));
  tft.drawRect(hx,hy,hw,hh,ST7735_WHITE);
  
  tft.drawRect(vx-1,vy-1,vw+2,vh+2,rgb565(128,128,128));
  tft.drawRect(vx+1,vy+1,vw-2,vh-2,rgb565(128,128,128));
  tft.drawRect(vx,vy,vw,vh,ST7735_WHITE);
  
  tft.drawCircle(cx,cy,cr+1,rgb565(128,128,128));
  tft.drawCircle(cx,cy,cr-1,rgb565(128,128,128));
  tft.drawCircle(cx,cy,cr,ST7735_WHITE);
}

void display_graphic(){
  
  if(x_value!=old_x_value){
    
    tft.drawRect(hx+hw/2+constrain(old_x_value,-hw/2+(hb+1)/2,hw/2-(hb+1)/2)-(hb-1)/2,hy+2,hb,hh-4,rgb565(0,0,0));
    tft.drawRect(hx+hw/2,hy+2,1,hh-4,rgb565(255,255,255));
    tft.drawRect(hx+hw/2+constrain(x_value,-hw/2+(hb+1)/2,hw/2-(hb+1)/2)-(hb-1)/2,hy+2,hb,hh-4,rgb565(0+constrain(abs(x_value)*10,0,255),255-constrain(abs(x_value)*10,0,255),0));
  }
    if(y_value!=old_y_value){
    
    tft.drawRect(vx+2,vy+vh/2-(constrain(old_y_value,-vh/2+(vb+1)/2,vh/2-(vb+1)/2)+(vb-1)/2),vw-4,vb,rgb565(0,0,0));
    tft.drawRect(vx+2,vy+vh/2,vw-4,1,rgb565(255,255,255));
    tft.drawRect(vx+2,vy+vh/2-(constrain(y_value,-vh/2+(vb+1)/2,vh/2-(vb+1)/2)+(vb-1)/2),vw-4,vb,rgb565(0+constrain(abs(y_value)*10,0,255),255-constrain(abs(y_value)*10,0,255),0));
  }
  if((x_value!=old_x_value)||(y_value!=old_y_value)){

    float hxv=old_x_value;
    float hyv=old_y_value;
    float l=sqrt(hxv*hxv+hyv*hyv);
    if(l>cr-cb-2){
      hxv=hxv/l*(cr-cb-2);
      hyv=hyv/l*(cr-cb-2);
    }
    
    tft.fillCircle(cx+hxv,cy-hyv,cb,rgb565(0,0,0));
    tft.drawCircle(cx,cy,cb+2,rgb565(255,255,255));
    
    hxv=x_value;
    hyv=y_value;
    l=sqrt(hxv*hxv+hyv*hyv);
    if(l>cr-cb-2){
      hxv=hxv/l*(cr-cb-2);
      hyv=hyv/l*(cr-cb-2);
    }
    tft.fillCircle(cx+hxv,cy-hyv,cb,rgb565(0+constrain((((abs(x_value)+abs(y_value))/2)*10),0,255),255-constrain((((abs(x_value)+abs(y_value))/2)*10),0,255),0));
  }
}

void display_info(){
     
  if(x_value!=old_x_value){
  
    set_text(4,16,value_to_string(old_x_value),ST7735_BLACK,1);
    set_text(4,16,value_to_string(x_value),ST7735_WHITE,1);
  }
  
    if(y_value!=old_y_value){
    
    set_text(4,26,value_to_string(old_y_value),ST7735_BLACK,1);
    set_text(4,26,value_to_string(y_value),ST7735_WHITE,1);
  }
}


void set_text(int x,int y,String text,int color,int size){
  
  tft.setTextSize(size);
  tft.setCursor(x,y);
  tft.setTextColor(color);
  tft.print(text);
}

// Hilfsfunktionen
uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b){

  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

String value_to_string(int value){
  
  String value_string = String(value);
  return value_string;
}

I don't know if the value can be stored to the Epsom? ?

A town in Surrey famed for its salts and The Derby horse-race ? No.

Try the EEPROM.

Looks similar to http://forum.arduino.cc/index.php?topic=333941.msg2304116#msg2304116

AWOL: A town in Surrey famed for its salts and The Derby horse-race ? No.

Try the EEPROM.

Oops stupid phone auto correct!

[quote author=Nick Gammon link=msg=2305272 date=1436168394] Looks similar to http://forum.arduino.cc/index.php?topic=333941.msg2304116#msg2304116 [/quote]

Yeah that's my post as well. I have worked out how to add my own "user guide"

I still need to work out the saving the calibration so it reverts to that when I re power on.

I am so new to this and learning by the day, but run before walk springs to mind!

I still need to work out the saving the calibration so it reverts to that when I re power on.

When/if the calibration changes within the program save the value to EEPROM. Each time the program starts read the value from EEPROM. Job done.

UKHeliBob: When/if the calibration changes within the program save the value to EEPROM. Each time the program starts read the value from EEPROM. Job done.

I thought I might be on track with the EEPROM, Now all I have to do is work out how on earth I do that! I have gone from making an LED Blink to writing lines of text...... now just figure out how to use the EEPROM.

If anyone has any tips I would be great full. I will try research it later.

If you open up your IDE, go to "File/Examples/EEPROM" you should find stuff there to get you started.

Topic: Save after power off

Wouldn't it make more sense to save the data BEFORE power off?

PaulS: Wouldn't it make more sense to save the data BEFORE power off?

But more challenging, Paul, to do it after it is too late. Like, shutting the stable door after the horse has been stolen.

I'm guessing from the comments that no one else is as good as they seem! I can manage to Google, and I can manage to write a question that might be worded slightly incorrectly. I have written the post on my phone during a 15 min break so I apologise if it's not perfect. As the guide states, I have attached the Sketch. I am new to this, I don't even understand the Sketch yet! I am wanting to learn and I'm getting there all be it slowly. I would appreciate some actual help, if you're as good as writing code as you are at wit, we will be off to a flying start.

If not, come the weekend, I will try to learn more and understand how to do this.

Many thanks

Sorry, that auto-correct feature can be a pain. A little while back I tried to type a message to my wife, and it kept "correcting" it from what I really wanted to say, to something that made no sense at all. Swearing at the phone didn't seem to help, either.

In brief, if you calibrate the device by pressing a button, that would be a good time to write that figure into EEPROM. The EEPROM defaults to 0xFF in every byte, so for an int, that would be -1 as the default value. If the value you read from EEPROM is either -1, or nonsense, then ignore it.

Also see reply #7.

I’m Sorry guys, :confused: I have gone through this as much as my ability allows.
I can work out how to serial print the current reading of the ADXL345, and I can roughly understand how the reading is displayed on the TFT, and how the calibration button sets the position of the display to the “0” position on the TFT.

I have tried writing to the EEprom and then reading from it and trying to print it on the serial monitor, the code is accepted, but it does not show anything.

To be honest I am totally out of my depth here. I have tried to research this, but it’s just too confusing.

I have put the sketch below, and I will ask for a last time if anyone can help me save the reading of the x and y values Once the calibration has occurred, and then when I re power on, take the reading so that it remembers where the calibration point is “So to speak”
You can see in the sketch where I have tried to work out saving to the EEPROM.

Please can someone tell me what to put.

Many thanks

#include <Wire.h>
#include <ADXL345.h>
#include <EEPROM.h>

#define cs   10 // Arduino-Pin an Display CS   
#define dc   9  // Arduino-Pin an Display A0
#define rst  8  // Arduino Reset-Pin

#include "Adafruit_GFX.h"    // Adafruit Grafik-Libary
#include "Adafruit_ST7735.h" // Adafruit ST7735-Libary
#include <SPI.h>

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);  // Display-Libary Setup


ADXL345 accel;

#define button_correction 3

// the current address in the EEPROM (i.e. which byte
// we're going to write to next)
int addr = 0;
int address = 0;
int valuex;

void setup(void){

  Serial.begin(9600);

  pinMode(button_correction, INPUT);

  // Sensor
  accel.begin();        // Sensor initialisation
  accel.setRange(accel.RANGE_4G);  // Setting Sensitivity
  
  // Display
  tft.initR(INITR_BLACKTAB);    // ST7735-Chip initialisation
  tft.setTextWrap(true); 
  
  display_show();
}

const float alpha = 0.5;
double fXg = 0;
double fYg = 0;
double fZg = 0;

double x_correction=0;
double y_correction=0;

int x_value=0;
int y_value=0;
int old_x_value=1;
int old_y_value=1;

#define filter_count_max 40
byte filter_count=0;
byte value;
#define correction_precision 300  // Display reduced wiggle

void loop(void){
 
  double pitch, roll, Xg, Yg, Zg;
  accel.read(&Xg, &Yg, &Zg);
  
  fXg+=Xg;
  fYg+=Yg;
  filter_count++;
  
  if(filter_count==filter_count_max-1){
  
    fXg/=filter_count_max;
    fYg/=filter_count_max;

    if(digitalRead(button_correction)==HIGH){
      x_correction=fXg; 
      y_correction=fYg;
    }
    
    x_value=(fXg-x_correction)*correction_precision;
    y_value=(fYg-y_correction)*correction_precision;

    //display_info();
    display_graphic();
    
    old_x_value=x_value;
    old_y_value=y_value;
    
    fXg=0;
    fYg=0;
    filter_count=0;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Serial.println(Xg);
    //Serial.println(Yg);
    //delay(5);

 
  int val1 = (Xg);
  
  EEPROM.write(addr, val1);
  
  
  
  delay(100);

  
// start reading from the first byte (address 0) of the EEPROM




  // initialize serial and wait for port to open:
 // Serial.begin(9600);
 // while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
}


  // read a byte from the current address of the EEPROM
void epromr()
{
 EEPROM.read(address); 
 
  Serial.print(address);
 // Serial.print("\t");
 // Serial.print(value, DEC);
  //Serial.println();
}
  // advance to the next address of the EEPROM
  //address = address + 1;
  
  // there are only 512 bytes of EEPROM, from 0 to 511, so if we're
  // on address 512, wrap around to address 0
 // if (address == 512)
  //  address = 0;
    
  //delay(500);

  
//  delay(5);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define hx 27
#define hy 16
#define hw 95
#define hh 18
#define hb 7

#define vx 5
#define vy 38
#define vw 18
#define vh 95
#define vb 7

#define cx 75
#define cy 86
#define cr 45
#define cb 5

void display_show(){

  tft.fillScreen(ST7735_BLACK); 

   delay(2000); // 2 Sekunden warten
  
  // Fontgroesse setzen
  // setTextSize(groesse);
  tft.setTextSize(2);
  
  // Schrift umbrechen?
  // setTextWrap(true);   true=Ja, false=Nein
  tft.setTextWrap(true); 
  
  // Textposition setzen
  // setCursor(x,y);
  tft.setCursor(24,4);
 
  // Textfarbe setzen
  // setTextColor(farbe);
  tft.setTextColor(ST7735_WHITE);
  
  // Text ausgeben
  // print(text);
  tft.println("Hello");
  tft.println("");
  delay(2000);
  tft.println("Charlies");
  tft.println("Spirit");
  tft.println("Level");
  tft.println("");
  delay(1000);
  tft.println("Calibrate");
  tft.println("Before use");
  

  delay(9000); // 2 Sekunden warten

  tft.fillScreen(ST7735_BLACK);

  delay(2000);
  
  set_text(32,3,"Spirit Level",ST7735_BLUE,1);  
  set_text(14,149,"By Charles Brennan",ST7735_GREEN,1);
  
  tft.drawRect(hx-1,hy-1,hw+2,hh+2,rgb565(128,128,128));
  tft.drawRect(hx+1,hy+1,hw-2,hh-2,rgb565(128,128,128));
  tft.drawRect(hx,hy,hw,hh,ST7735_WHITE);
  
  tft.drawRect(vx-1,vy-1,vw+2,vh+2,rgb565(128,128,128));
  tft.drawRect(vx+1,vy+1,vw-2,vh-2,rgb565(128,128,128));
  tft.drawRect(vx,vy,vw,vh,ST7735_WHITE);
  
  tft.drawCircle(cx,cy,cr+1,rgb565(128,128,128));
  tft.drawCircle(cx,cy,cr-1,rgb565(128,128,128));
  tft.drawCircle(cx,cy,cr,ST7735_WHITE);
}

void display_graphic(){
  
  if(x_value!=old_x_value){
    
    tft.drawRect(hx+hw/2+constrain(old_x_value,-hw/2+(hb+1)/2,hw/2-(hb+1)/2)-(hb-1)/2,hy+2,hb,hh-4,rgb565(0,0,0));
    tft.drawRect(hx+hw/2,hy+2,1,hh-4,rgb565(255,255,255));
    tft.drawRect(hx+hw/2+constrain(x_value,-hw/2+(hb+1)/2,hw/2-(hb+1)/2)-(hb-1)/2,hy+2,hb,hh-4,rgb565(0+constrain(abs(x_value)*10,0,255),255-constrain(abs(x_value)*10,0,255),0));
  }
    if(y_value!=old_y_value){
    
    tft.drawRect(vx+2,vy+vh/2-(constrain(old_y_value,-vh/2+(vb+1)/2,vh/2-(vb+1)/2)+(vb-1)/2),vw-4,vb,rgb565(0,0,0));
    tft.drawRect(vx+2,vy+vh/2,vw-4,1,rgb565(255,255,255));
    tft.drawRect(vx+2,vy+vh/2-(constrain(y_value,-vh/2+(vb+1)/2,vh/2-(vb+1)/2)+(vb-1)/2),vw-4,vb,rgb565(0+constrain(abs(y_value)*10,0,255),255-constrain(abs(y_value)*10,0,255),0));
  }
  if((x_value!=old_x_value)||(y_value!=old_y_value)){

    float hxv=old_x_value;
    float hyv=old_y_value;
    float l=sqrt(hxv*hxv+hyv*hyv);
    if(l>cr-cb-2){
      hxv=hxv/l*(cr-cb-2);
      hyv=hyv/l*(cr-cb-2);
    }
    
    tft.fillCircle(cx+hxv,cy-hyv,cb,rgb565(0,0,0));
    tft.drawCircle(cx,cy,cb+2,rgb565(255,255,255));
    
    hxv=x_value;
    hyv=y_value;
    l=sqrt(hxv*hxv+hyv*hyv);
    if(l>cr-cb-2){
      hxv=hxv/l*(cr-cb-2);
      hyv=hyv/l*(cr-cb-2);
    }
    tft.fillCircle(cx+hxv,cy-hyv,cb,rgb565(0+constrain((((abs(x_value)+abs(y_value))/2)*10),0,255),255-constrain((((abs(x_value)+abs(y_value))/2)*10),0,255),0));
  }
}

void display_info(){
     
  if(x_value!=old_x_value){
  
    set_text(4,16,value_to_string(old_x_value),ST7735_BLACK,1);
    set_text(4,16,value_to_string(x_value),ST7735_WHITE,1);
  }
  
    if(y_value!=old_y_value){
    
    set_text(4,26,value_to_string(old_y_value),ST7735_BLACK,1);
    set_text(4,26,value_to_string(y_value),ST7735_WHITE,1);
  }
}


void set_text(int x,int y,String text,int color,int size){
  
  tft.setTextSize(size);
  tft.setCursor(x,y);
  tft.setTextColor(color);
  tft.print(text);
}

// Auxillary Functions
uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b){

  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

String value_to_string(int value){
  
  String value_string = String(value);
  return value_string;
}
  int val1 = (Xg);
  
  EEPROM.write(addr, val1);

I see at least 2 problems. Xg is declared as a double (4 bytes) but you are trying to put its value into an int (2 bytes) Then you are writing an int (2 bytes) into a single byte EEPROM location.

There is a small templated function that helps put things like floats into EEPROM (and get them back):

http://playground.arduino.cc/Code/EEPROMWriteAnything

I have worked how to save to the EEPROM, but I seem to be getting the reading that is sent to the TFT display as opposed to the actual readings of the ADXL345.
This was when I pressed the calibration button 3 separate times:
x = 0
y = -1
x = 0
y = 0
x = 0
y = -1

So I need to find out why I’m not saving the actual data of the ADXL345, and also once I have done that, I need to know how I can read the data saved next time I do a power cycle, so that I don’t have to calibrate it each time I power off/reset.

I’m seriously running out of time on this project as I need it for the week after next, and I’m away a few days this week :frowning:

Here is my latest Sketch

#include <Wire.h>
#include <ADXL345.h>
#include <EEPROM.h>
#include "eetest.h"

#define cs   10 // Arduino-Pin an Display CS   
#define dc   9  // Arduino-Pin an Display A0
#define rst  8  // Arduino Reset-Pin

#include "Adafruit_GFX.h"    // Adafruit Grafik-Libary
#include "Adafruit_ST7735.h" // Adafruit ST7735-Libary
#include <SPI.h>

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);  // Display-Libary Setup


ADXL345 accel;

#define button_correction 3

//////////////////////////////////////////////////////////////////////////////////////////////
struct config_t
{
   long x;
   int y;
} configuration;
//////////////////////////////////////////////////////////////////////////////////////////////



void setup(void){

  Serial.begin(9600);

  pinMode(button_correction, INPUT);

  // Sensor
  accel.begin();        // Sensor initialisation
  accel.setRange(accel.RANGE_4G);  // Setting Sensitivity
  
  // Display
  tft.initR(INITR_BLACKTAB);    // ST7735-Chip initialisation
  tft.setTextWrap(true); 
  
  display_show();
}

const float alpha = 0.5;
double fXg = 0;
double fYg = 0;
double fZg = 0;

double x_correction=0;
double y_correction=0;

int x_value=0;
int y_value=0;
int old_x_value=1;
int old_y_value=1;

#define filter_count_max 40
byte filter_count=0;

#define correction_precision 300  // Display reduced wiggle

void loop(void){
 
  double pitch, roll, Xg, Yg, Zg;
  accel.read(&Xg, &Yg, &Zg);
  
  fXg+=Xg;
  fYg+=Yg;
  filter_count++;
  
  if(filter_count==filter_count_max-1){
  
    fXg/=filter_count_max;
    fYg/=filter_count_max;

    if(digitalRead(button_correction)==HIGH){
      x_correction=fXg; 
      y_correction=fYg;
      //////////////////////////////////////////////////////////////////////////////////////////////////
      configuration.x = (Xg);
      configuration.y = (Yg);
      
   // Write the configuration struct to EEPROM
   EEPROM_writeAnything(0, configuration);
//      readcal();

// Read and print the contents of EEPROM
   EEPROM_readAnything(0, configuration);    
   Serial.print("x  = ");Serial.println(configuration.x);
   Serial.print("y   = ");Serial.println(configuration.y);

  // A "do nothing loop" where your real working code would be
   // while(1)
    ;
////////////////////////////////////////////////////////////////////////////////////////////////////////
    }
    
    x_value=(fXg-x_correction)*correction_precision;
    y_value=(fYg-y_correction)*correction_precision;

    //display_info();
    display_graphic();
    
    old_x_value=x_value;
    old_y_value=y_value;
    
    fXg=0;
    fYg=0;
    filter_count=0;

     }
  
  delay(5);

}

#define hx 27
#define hy 16
#define hw 95
#define hh 18
#define hb 7

#define vx 5
#define vy 38
#define vw 18
#define vh 95
#define vb 7

#define cx 75
#define cy 86
#define cr 45
#define cb 5

void display_show(){

  tft.fillScreen(ST7735_BLACK); 

   delay(2000); // 2 Sekunden warten
  
  // Fontgroesse setzen
  // setTextSize(groesse);
  tft.setTextSize(2);
  
  // Schrift umbrechen?
  // setTextWrap(true);   true=Ja, false=Nein
  tft.setTextWrap(true); 
  
  // Textposition setzen
  // setCursor(x,y);
  tft.setCursor(24,4);
 
  // Textfarbe setzen
  // setTextColor(farbe);
  tft.setTextColor(ST7735_WHITE);
  
  // Text ausgeben
  // print(text);
  tft.println("Hello");
  tft.println("");
  delay(2000);
  tft.println("Charlies");
  tft.println("Spirit");
  tft.println("Level");
  tft.println("");
  delay(1000);
  tft.println("Calibrate");
  tft.println("Before use");
  

  delay(2000); // 2 Sekunden warten

  tft.fillScreen(ST7735_BLACK);

  delay(2000);
  
  set_text(32,3,"Spirit Level",ST7735_BLUE,1);  
  set_text(14,149,"By Charles Brennan",ST7735_GREEN,1);
  
  tft.drawRect(hx-1,hy-1,hw+2,hh+2,rgb565(128,128,128));
  tft.drawRect(hx+1,hy+1,hw-2,hh-2,rgb565(128,128,128));
  tft.drawRect(hx,hy,hw,hh,ST7735_WHITE);
  
  tft.drawRect(vx-1,vy-1,vw+2,vh+2,rgb565(128,128,128));
  tft.drawRect(vx+1,vy+1,vw-2,vh-2,rgb565(128,128,128));
  tft.drawRect(vx,vy,vw,vh,ST7735_WHITE);
  
  tft.drawCircle(cx,cy,cr+1,rgb565(128,128,128));
  tft.drawCircle(cx,cy,cr-1,rgb565(128,128,128));
  tft.drawCircle(cx,cy,cr,ST7735_WHITE);
}

void display_graphic(){
  
  if(x_value!=old_x_value){
    
    tft.drawRect(hx+hw/2+constrain(old_x_value,-hw/2+(hb+1)/2,hw/2-(hb+1)/2)-(hb-1)/2,hy+2,hb,hh-4,rgb565(0,0,0));
    tft.drawRect(hx+hw/2,hy+2,1,hh-4,rgb565(255,255,255));
    tft.drawRect(hx+hw/2+constrain(x_value,-hw/2+(hb+1)/2,hw/2-(hb+1)/2)-(hb-1)/2,hy+2,hb,hh-4,rgb565(0+constrain(abs(x_value)*10,0,255),255-constrain(abs(x_value)*10,0,255),0));
  }
    if(y_value!=old_y_value){
    
    tft.drawRect(vx+2,vy+vh/2-(constrain(old_y_value,-vh/2+(vb+1)/2,vh/2-(vb+1)/2)+(vb-1)/2),vw-4,vb,rgb565(0,0,0));
    tft.drawRect(vx+2,vy+vh/2,vw-4,1,rgb565(255,255,255));
    tft.drawRect(vx+2,vy+vh/2-(constrain(y_value,-vh/2+(vb+1)/2,vh/2-(vb+1)/2)+(vb-1)/2),vw-4,vb,rgb565(0+constrain(abs(y_value)*10,0,255),255-constrain(abs(y_value)*10,0,255),0));
  }
  if((x_value!=old_x_value)||(y_value!=old_y_value)){

    float hxv=old_x_value;
    float hyv=old_y_value;
    float l=sqrt(hxv*hxv+hyv*hyv);
    if(l>cr-cb-2){
      hxv=hxv/l*(cr-cb-2);
      hyv=hyv/l*(cr-cb-2);
    }
    
    tft.fillCircle(cx+hxv,cy-hyv,cb,rgb565(0,0,0));
    tft.drawCircle(cx,cy,cb+2,rgb565(255,255,255));
    
    hxv=x_value;
    hyv=y_value;
    l=sqrt(hxv*hxv+hyv*hyv);
    if(l>cr-cb-2){
      hxv=hxv/l*(cr-cb-2);
      hyv=hyv/l*(cr-cb-2);
    }
    tft.fillCircle(cx+hxv,cy-hyv,cb,rgb565(0+constrain((((abs(x_value)+abs(y_value))/2)*10),0,255),255-constrain((((abs(x_value)+abs(y_value))/2)*10),0,255),0));
  }
}

void display_info(){
     
  if(x_value!=old_x_value){
  
    set_text(4,16,value_to_string(old_x_value),ST7735_BLACK,1);
    set_text(4,16,value_to_string(x_value),ST7735_WHITE,1);
  }
  
    if(y_value!=old_y_value){
    
    set_text(4,26,value_to_string(old_y_value),ST7735_BLACK,1);
    set_text(4,26,value_to_string(y_value),ST7735_WHITE,1);
  }
}


void set_text(int x,int y,String text,int color,int size){
  
  tft.setTextSize(size);
  tft.setCursor(x,y);
  tft.setTextColor(color);
  tft.print(text);
}

// Auxillary Functions
uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b){

  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

String value_to_string(int value){
  
  String value_string = String(value);
  return value_string;
}

include "eetest.h"

Did you show us a copy of this earlier in the thread? I can't see it.

MorganS:
Did you show us a copy of this earlier in the thread? I can’t see it.

Sorry it’s here

#include <Arduino.h>
template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
   const byte* p = (const byte*)(const void*)&value;
   int i;
   for (i = 0; i < sizeof(value); i++)
       EEPROM.write(ee++, *p++);
   return i;
}

template <class T> int EEPROM_readAnything(int ee, T& value)
{
   byte* p = (byte*)(void*)&value;
   int i;
   for (i = 0; i < sizeof(value); i++)
       *p++ = EEPROM.read(ee++);
   return i;
}
struct config_t

{
  long x;
  int y;
} configuration;

Why are x and y different types? That already looks suspect.

double fXg = 0;

double fYg = 0;

void loop(void){

double pitch, roll, Xg, Yg, Zg;
 accel.read(&Xg, &Yg, &Zg);
 
 fXg+=Xg;
 fYg+=Yg;
 filter_count++;
 
 if(filter_count==filter_count_max-1){
 
   fXg/=filter_count_max;
   fYg/=filter_count_max;

if(digitalRead(button_correction)==HIGH){
     x_correction=fXg;
     y_correction=fYg;
     //////////////////////////////////////////////////////////////////////////////////////////////////
     configuration.x = (Xg);
     configuration.y = (Yg);
     
  // Write the configuration struct to EEPROM
  EEPROM_writeAnything(0, configuration);

So you seem to create a pair of correction variables but then you store into your configuration struct, simply the last two X and Y values. Even if you were to try to store the corrections, this won’t work as you’re trying to store a floating point value around -1 to +1 into an integer, which can only store -1, 0 or +1.

First, since you appear to need floating-point corrections, the struct should be defined with floats. Then you need to store the correct values. THEN you need a way of loading those values out of the EEPROM, without just oevrwriting with the new correction every single time it starts.

Try this overall structure:

//define all your global variables at the top, above any function such as setup()
////////////////////////////////////////////////
void setup() {
  //do the other setup stuff like initialising the ADXL345
  ////////////////////////////////////////////////
  if(EEPROM.read(MARKERBYTE) != 0) {
    //EEPROM has not been initialised - immediately do a calibration
    accelCalibrate(); //note this will update the variables x_correction and y_correction
    EEPROM_writeAnything(XLOCATION, x_correction);
    EEPROM_writeAnything(YLOCATION, y_correction);
    EEPROM.write(MARKERBYTE, 0) //save zero to the marker so we know the EEPROM has a valid calibration
  } else {
    //we have a valid calibration - load that instead of doing a full calibrate
    EEPROM_readAnything(XLOCATION, x_correction);
    EEPROM_readAnything(YLOCATION, y_correction);
  }
}

Actually, since I’d want to have a button to re-calibrate at any time, I would put the EEPROM write into the accelCalibrate() function and I’d set up some logic to test that button inside the main loop as well.

Quote
Code: [Select]
struct config_t
{
long x;
int y;
} configuration;

Why are x and y different types? That already looks suspect.

I am totally new to this and just copying and guessing what to do!

Try this overall structure:
Code: [Select]

//define all your global variables at the top, above any function such as setup()
////////////////////////////////////////////////
void setup() {
//do the other setup stuff like initialising the ADXL345
////////////////////////////////////////////////
if(EEPROM.read(MARKERBYTE) != 0) {
//EEPROM has not been initialised - immediately do a calibration
accelCalibrate(); //note this will update the variables x_correction and y_correction
EEPROM_writeAnything(XLOCATION, x_correction);
EEPROM_writeAnything(YLOCATION, y_correction);
EEPROM.write(MARKERBYTE, 0) //save zero to the marker so we know the EEPROM has a valid calibration
} else {
//we have a valid calibration - load that instead of doing a full calibrate
EEPROM_readAnything(XLOCATION, x_correction);
EEPROM_readAnything(YLOCATION, y_correction);
}
}

I Have tried to put this in my sketch, but as I said above, I really am over my level of limited knowledge here.
I get an error message, I know I have done your instructions wrong but I don’t know what to do.

This is the sketch

#include <Wire.h>
#include <ADXL345.h>
#include <EEPROM.h>
#include "eetest.h"

#define cs   10 // Arduino-Pin an Display CS   
#define dc   9  // Arduino-Pin an Display A0
#define rst  8  // Arduino Reset-Pin

#include "Adafruit_GFX.h"    // Adafruit Grafik-Libary
#include "Adafruit_ST7735.h" // Adafruit ST7735-Libary
#include <SPI.h>

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);  // Display-Libary Setup


ADXL345 accel;

#define button_correction 3



void setup(void){

  Serial.begin(9600);

   if(EEPROM.read(MARKERBYTE) != 0) {
    //EEPROM has not been initialised - immediately do a calibration
    accelCalibrate(); //note this will update the variables x_correction and y_correction
    EEPROM_writeAnything(XLOCATION, x_correction);
    EEPROM_writeAnything(YLOCATION, y_correction);
    EEPROM.write(MARKERBYTE, 0) //save zero to the marker so we know the EEPROM has a valid calibration
  } else {
    //we have a valid calibration - load that instead of doing a full calibrate
    EEPROM_readAnything(XLOCATION, x_correction);
    EEPROM_readAnything(YLOCATION, y_correction);
  }
}

  pinMode(button_correction, INPUT);

  // Sensor
  accel.begin();        // Sensor initialisation
  accel.setRange(accel.RANGE_4G);  // Setting Sensitivity
  
  // Display
  tft.initR(INITR_BLACKTAB);    // ST7735-Chip initialisation
  tft.setTextWrap(true); 
  
  display_show();
}

const float alpha = 0.5;
double fXg = 0;
double fYg = 0;
double fZg = 0;

double x_correction=0;
double y_correction=0;

int x_value=0;
int y_value=0;
int old_x_value=1;
int old_y_value=1;

#define filter_count_max 40
byte filter_count=0;

#define correction_precision 300  // Display reduced wiggle

void loop(void){
 
  double pitch, roll, Xg, Yg, Zg;
  accel.read(&Xg, &Yg, &Zg);
  
  fXg+=Xg;
  fYg+=Yg;
  filter_count++;
  
  if(filter_count==filter_count_max-1){
  
    fXg/=filter_count_max;
    fYg/=filter_count_max;

    if(digitalRead(button_correction)==HIGH){
      x_correction=fXg; 
      y_correction=fYg;
    
    }
    
    x_value=(fXg-x_correction)*correction_precision;
    y_value=(fYg-y_correction)*correction_precision;

    //display_info();
    display_graphic();
    
    old_x_value=x_value;
    old_y_value=y_value;
    
    fXg=0;
    fYg=0;
    filter_count=0;

     }
  
  delay(5);

}

#define hx 27
#define hy 16
#define hw 95
#define hh 18
#define hb 7

#define vx 5
#define vy 38
#define vw 18
#define vh 95
#define vb 7

#define cx 75
#define cy 86
#define cr 45
#define cb 5

void display_show(){

  tft.fillScreen(ST7735_BLACK); 

   delay(2000); // 2 Sekunden warten
  
  // Fontgroesse setzen
  // setTextSize(groesse);
  tft.setTextSize(2);
  
  // Schrift umbrechen?
  // setTextWrap(true);   true=Ja, false=Nein
  tft.setTextWrap(true); 
  
  // Textposition setzen
  // setCursor(x,y);
  tft.setCursor(24,4);
 
  // Textfarbe setzen
  // setTextColor(farbe);
  tft.setTextColor(ST7735_WHITE);
  
  // Text ausgeben
  // print(text);
  tft.println("Hello");
  tft.println("");
  delay(2000);
  tft.println("Charlies");
  tft.println("Spirit");
  tft.println("Level");
  tft.println("");
  delay(1000);
  tft.println("Calibrate");
  tft.println("Before use");
  

  delay(2000); // 2 Sekunden warten

  tft.fillScreen(ST7735_BLACK);

  delay(2000);
  
  set_text(32,3,"Spirit Level",ST7735_BLUE,1);  
  set_text(14,149,"By Charles Brennan",ST7735_GREEN,1);
  
  tft.drawRect(hx-1,hy-1,hw+2,hh+2,rgb565(128,128,128));
  tft.drawRect(hx+1,hy+1,hw-2,hh-2,rgb565(128,128,128));
  tft.drawRect(hx,hy,hw,hh,ST7735_WHITE);
  
  tft.drawRect(vx-1,vy-1,vw+2,vh+2,rgb565(128,128,128));
  tft.drawRect(vx+1,vy+1,vw-2,vh-2,rgb565(128,128,128));
  tft.drawRect(vx,vy,vw,vh,ST7735_WHITE);
  
  tft.drawCircle(cx,cy,cr+1,rgb565(128,128,128));
  tft.drawCircle(cx,cy,cr-1,rgb565(128,128,128));
  tft.drawCircle(cx,cy,cr,ST7735_WHITE);
}

void display_graphic(){
  
  if(x_value!=old_x_value){
    
    tft.drawRect(hx+hw/2+constrain(old_x_value,-hw/2+(hb+1)/2,hw/2-(hb+1)/2)-(hb-1)/2,hy+2,hb,hh-4,rgb565(0,0,0));
    tft.drawRect(hx+hw/2,hy+2,1,hh-4,rgb565(255,255,255));
    tft.drawRect(hx+hw/2+constrain(x_value,-hw/2+(hb+1)/2,hw/2-(hb+1)/2)-(hb-1)/2,hy+2,hb,hh-4,rgb565(0+constrain(abs(x_value)*10,0,255),255-constrain(abs(x_value)*10,0,255),0));
  }
    if(y_value!=old_y_value){
    
    tft.drawRect(vx+2,vy+vh/2-(constrain(old_y_value,-vh/2+(vb+1)/2,vh/2-(vb+1)/2)+(vb-1)/2),vw-4,vb,rgb565(0,0,0));
    tft.drawRect(vx+2,vy+vh/2,vw-4,1,rgb565(255,255,255));
    tft.drawRect(vx+2,vy+vh/2-(constrain(y_value,-vh/2+(vb+1)/2,vh/2-(vb+1)/2)+(vb-1)/2),vw-4,vb,rgb565(0+constrain(abs(y_value)*10,0,255),255-constrain(abs(y_value)*10,0,255),0));
  }
  if((x_value!=old_x_value)||(y_value!=old_y_value)){

    float hxv=old_x_value;
    float hyv=old_y_value;
    float l=sqrt(hxv*hxv+hyv*hyv);
    if(l>cr-cb-2){
      hxv=hxv/l*(cr-cb-2);
      hyv=hyv/l*(cr-cb-2);
    }
    
    tft.fillCircle(cx+hxv,cy-hyv,cb,rgb565(0,0,0));
    tft.drawCircle(cx,cy,cb+2,rgb565(255,255,255));
    
    hxv=x_value;
    hyv=y_value;
    l=sqrt(hxv*hxv+hyv*hyv);
    if(l>cr-cb-2){
      hxv=hxv/l*(cr-cb-2);
      hyv=hyv/l*(cr-cb-2);
    }
    tft.fillCircle(cx+hxv,cy-hyv,cb,rgb565(0+constrain((((abs(x_value)+abs(y_value))/2)*10),0,255),255-constrain((((abs(x_value)+abs(y_value))/2)*10),0,255),0));
  }
}

void display_info(){
     
  if(x_value!=old_x_value){
  
    set_text(4,16,value_to_string(old_x_value),ST7735_BLACK,1);
    set_text(4,16,value_to_string(x_value),ST7735_WHITE,1);
  }
  
    if(y_value!=old_y_value){
    
    set_text(4,26,value_to_string(old_y_value),ST7735_BLACK,1);
    set_text(4,26,value_to_string(y_value),ST7735_WHITE,1);
  }
}


void set_text(int x,int y,String text,int color,int size){
  
  tft.setTextSize(size);
  tft.setCursor(x,y);
  tft.setTextColor(color);
  tft.print(text);
}

// Auxillary Functions
uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b){

  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

String value_to_string(int value){
  
  String value_string = String(value);
  return value_string;
}