Hysteresis

Hi everybody.

I`m struggling to get the hysteresis to work, no matter on the value the screen flicker btw values as much as he like.
Any suggestions?
Thanks

#include "U8glib.h"

int anPin0 = A0;
int val0 = 0;
byte hysteresis = 10;

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here
  u8g.drawCircle(115, 3, 1.5);
  u8g.setFont(u8g_font_profont22);
  u8g.setPrintPos(0, 15);
  u8g.print("TEMP:     C");
  u8g.setPrintPos(60, 15);
  u8g.print(val0);
}

void setup(void) {
  // start serial port
  Serial.begin(9600);
  // flip screen, if required
  // u8g.setRot180();
}


void loop(void)
{
  val0 = analogRead(anPin0);
  Serial.println(val0);


  val0 = map(val0, 0, 1023, 0, 60);
  if (val0 < (val0 + hysteresis))
  {
    updateOled();
  }
  else if (val0 > (val0 - hysteresis))
  {
    updateOled();
  }
  delay(50);
}
void updateOled(void)
{ // picture loop
  u8g.firstPage();

  do {
    draw();
  } while ( u8g.nextPage() );
}

Your code

  if (val0 < (val0 + hysteresis))
  {
    updateOled();
  }
  else if (val0 > (val0 - hysteresis))
  {
    updateOled();
  }

As val0 is always positive and hysteresis is positive, the if condition will always evaluate true.

What you probably want is to remember the previous value and compare the old value with the new value taking hysteresis into account.

Can you suggest syntax please?

sterretje:
As val0 is always positive and hysteresis is positive, the if condition will always evaluate true.

What you probably want is to remember the previous value and compare the old value with the new value taking hysteresis into account.

BOTH conditions evaluate to TRUE! Once you make the change @sterretje suggested, I think you also need to swap the "less than" and "greater than" comparisons.

can you really interpret your data every 50ms?

void loop(void)
{
  val0 = analogRead(anPin0);
  Serial.println(val0);


  val0 = map(val0, 0, 1023, 0, 60);
  if (val0 < (val0 + hysteresis))
  {
    updateOled();
  }
  else if (val0 > (val0 - hysteresis))
  {
    updateOled();
  }
  delay(50);
}

slow it down:

void loop(void)
{
  static unsigned long lastReadingMillis = 0;
  if(millis() - lastReadingMillis > 1000) . // once a second
  {
    val0 = analogRead(anPin0);
    Serial.println(val0);
    val0 = map(val0, 0, 1023, 0, 60);
    updateOled();
    lastReadingMillis = millis();
  }
}

then tweak your hysteresis or use some time-averaging.

bulldoglowell i did longer delay already and it makes reading on the screen consistent, but then the screen becomes laggy when you want to update the screen with more frequent data

Also i`m not sure if remembering the old value is correct in this

#include "U8glib.h"

int anPin0 = A0;
int val0 = 0;
int oldvalue = 0;
byte hysteresis = 10;

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here
  u8g.drawCircle(115, 3, 1.5);
  u8g.setFont(u8g_font_profont22);
  u8g.setPrintPos(0, 15);
  u8g.print("TEMP:     C");
  u8g.setPrintPos(60, 15);
  u8g.print(val0);
}

void setup(void) {
  // start serial port
  Serial.begin(9600);
  // flip screen, if required
  // u8g.setRot180();
}


void loop(void)
{

  val0 = analogRead(anPin0);
  Serial.println(val0);
  oldvalue = val0;

  val0 = map(val0, 0, 1023, 0, 60);

  if (oldvalue < (val0 - hysteresis))
  {
    updateOled();
  }
  else if (oldvalue > (val0 + hysteresis))
  {
    updateOled();
  }
  delay(50);
}
void updateOled(void)
{ // picture loop
  u8g.firstPage();

  do {
    draw();
  } while ( u8g.nextPage() );
}

mOskit:
bulldoglowell i did longer delay already and it makes reading on the screen consistent, but then the screen becomes laggy when you want to update the screen with more frequent data

because you used delay()

look at the alternate code I gave you which should eliminate your laggy-ness.

Thants what im saying. It does exactly the same thing either with delay or millis and it`s still not solving the hysteresis issue. Working hysteresis should eliminate any need for delay i guess

mOskit:
Working hysteresis should eliminate any need for delay i guess

if you do it correctly. Maybe you should post your current code without delays.

mOskit:
Working hysteresis should eliminate any need for delay i guess

then why would you immediately set oldValue equal to the current reading?

  val0 = analogRead(anPin0);
  Serial.println(val0);
  oldvalue = val0;

my point was that the 50ms refresh rate is silly. If you get that normal, and then you can see if your hysteresis is working, which in its present state, well... isn't

I`m not quite sure where to place "oldvalue" within the code as sterretje suggested to use it.

Also to test hysteresis simply setting the value say to "10" should impact on the output as the display should not update if the value is - or + say 10 or more then the val0 . Correct me if i`m wrong.

mOskit:
Also to test hysteresis simply setting the value say to "10" should impact on the output as the display should not update if the value is - or + say 10 or more then the val0 . Correct me if i`m wrong.

something like this:

void loop(void)
{
  static int oldvalue = 0;
  int val0 = analogRead(anPin0);
  Serial.println(val0);
  val0 = map(val0, 0, 1023, 0, 60);
  if (val0 != oldvalue)
  {
    if (val0 > oldvalue + hysteresis or val0 < oldvalue - hysteresis)
    {
      oldValue = val0;
      updateOled();
    }
  }
}

I'd set:

static int oldvalue = -1000;

To make sure the hysteresis fires at least once.
Or maybe:

#include <limits.h>
static int oldvalue = INT_MIN;

[/code]

gfvalvo:
Or maybe:

#include <limits.h>

static int oldvalue = INT_MIN;



[/code]

silliness

I'll give you:

static int oldvalue = -1;

analogRead cannot return a negative number

What happens if the first read returns 0 and 'hysteresis' is 10?

Split the difference:

static int oldvalue = -hysteresis -1;

gfvalvo:
What happens if the first read returns 0 and 'hysteresis' is 10?

Split the difference:

static int oldvalue = -hysteresis -1;

yep, plush the OP should be able to figure out this on his/her own, too.

:wink:

Thanks for all your effort.
Screen returns constant zero which means that the "if" statement is not being executed.

#include "U8glib.h"
#include "limits.h"

int anPin0 = A0;
int val0 = 0;
//int oldvalue = 0;
byte hysteresis = 10;

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here
  u8g.drawCircle(115, 3, 1.5);
  u8g.setFont(u8g_font_profont22);
  u8g.setPrintPos(0, 15);
  u8g.print("TEMP:     C");
  u8g.setPrintPos(60, 15);
  u8g.print(val0);
}

void setup(void) {
  // start serial port
  Serial.begin(9600);
  // flip screen, if required
  // u8g.setRot180();
}



void loop(void)
{
  static int oldvalue = -hysteresis - 1;
  int val0 = analogRead(anPin0);
  Serial.println(val0);
  val0 = map(val0, 0, 1023, 0, 60);
  if (val0 != oldvalue)
  {
    if (val0 > oldvalue + hysteresis or val0 < oldvalue - hysteresis)
    {
      oldvalue = val0;
      updateOled();
    }
  }
}
void updateOled(void)
{ // picture loop
  u8g.firstPage();

  do {
    draw();
  } while ( u8g.nextPage() );
}

whai is interested in this now is that the oldvalue is being affected by hysteresis. See print screen

#include "U8glib.h"
#include "limits.h"

int anPin0 = A0;
int val0 = 0;
int oldvalue = 0;
byte hysteresis = 10;

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here
  u8g.drawCircle(115, 3, 1.5);
  u8g.setFont(u8g_font_profont22);
  u8g.setPrintPos(0, 15);
  u8g.print("TEMP:     C");
  u8g.setPrintPos(60, 15);
  u8g.print(val0);
}

void setup(void) {
  // start serial port
  Serial.begin(9600);
  // flip screen, if required
  // u8g.setRot180();
}



void loop(void)
{
  //static int oldvalue = -hysteresis - 1;
  int val0 = analogRead(anPin0);

  val0 = map(val0, 0, 1023, 0, 60);
  Serial.print("VAL0= ");
  Serial.print(val0);
  Serial.print(" oldvalue= ");
  Serial.println(oldvalue);
  if (val0 != oldvalue)
  {
    if (val0 > oldvalue + hysteresis or val0 < oldvalue - hysteresis)
    {
      oldvalue = val0;
      updateOled();
    }
  }
}
void updateOled(void)
{ // picture loop
  u8g.firstPage();

  do {
    draw();
  } while ( u8g.nextPage() );
}

so finally, static int oldvalue = -hysteresis -1; not updating the screen.
The only way to get it fairly stable was this

#include "U8glib.h"
//#include "limits.h"

int anPin0 = A0;
int val0 = 0;
int oldvalue = 0;
byte hysteresis = 1;

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here
  u8g.drawCircle(115, 3, 1.5);
  u8g.setFont(u8g_font_profont22);
  u8g.setPrintPos(0, 15);
  u8g.print("TEMP:     C");
  u8g.setPrintPos(60, 15);
  u8g.print(oldvalue);
}

void setup(void) {
  // start serial port
  Serial.begin(9600);
  // flip screen, if required
  // u8g.setRot180();
}



void loop(void)
{
  // static int oldvalue = -hysteresis - 1;
  int val0 = analogRead(anPin0);

  val0 = map(val0, 0, 1023, 0, 60);
  Serial.print("VAL0= ");
  Serial.print(val0);
  Serial.print(" oldvalue= ");
  Serial.println(oldvalue);
  if (oldvalue != val0)
  {
    if (val0 > oldvalue + hysteresis or val0 < oldvalue - hysteresis)
    {
      (oldvalue = (val0 - 1));
      updateOled();
    }
    else if (val0 = 0)
    {
      oldvalue = 0;
      updateOled();
    }
  }
}
void updateOled(void)
{ // picture loop
  u8g.firstPage();

  do {
    draw();
  } while ( u8g.nextPage() );
}

The (oldvalue = (val0-1)); is to stop updating the screen every second value, but this created a deviation of 1.
thanks for your help