olikraus / u8g2

U8glib library for monochrome displays, version 2
Other
4.91k stars 1.03k forks source link

Volt-termometer work with SSD1306, don't work with SH1106 #2371

Open fratellos opened 4 months ago

fratellos commented 4 months ago

Hi ! I intend to build for my car an volt-termometer. I use the attached schematic : Arduino Nano, oled display 1.3" SH1106, DS18B20. I tried several version of code , with both u8glib and u8g2lib... but I can figured out why, after a while, the code is crashing. The info (values of temp and voltage) on display don't change anymore ... I need to cut the power of Arduino ! I really don't understand what happens. With 0.96 " Oled display work flawless, with 1.3 (SH1106) Oled display don't. Please, I need help. Thanks in advance ! Regards !

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include "U8g2lib.h"     

#define ONE_WIRE_BUS 2 //Pin DS al senzorului DS18B20

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;

U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);   

int analogInput = 0;
float vout = 0.0;
float vin = 0.0;
float R1 = 100000.0; // resistance of R1 (100K)
float R2 =  10000.0; // resistance of R2 (10K) 
int value = 0;

double temp;

void setup() { 
  u8g2.begin();
  pinMode(analogInput, INPUT);
  sensors.begin();
  sensors.setResolution(tempDeviceAddress, 11);
}

void loop() {
u8g2.clearBuffer();
   value = analogRead(analogInput);
   vout = (value * 5.0) / 1024.0; 
   vin = vout / (R2/(R1+R2)); 

if (vin<0.09) {
  vin=0.0;//statement to quash undesired reading !
  }

sensors.requestTemperatures();
  float tempC = sensors.getTempCByIndex(0); 
  if (tempC != DEVICE_DISCONNECTED_C)
  {
    temp=tempC;
  }
  else
  {
    temp= 99.9;  //aici mesajul de eroare senzor !!!!
  }

u8g2.firstPage();
do
   {
    draw();
   }
while ( u8g2.nextPage() ); 
delay(1000);

}

void draw(void)
{

  u8g2.setFont(u8g2_font_helvB24_tf);
  u8g2.drawRFrame(0, 30, 128, 32, 10);     // draws frame with rounded edges

if (vin>9.99) {
  u8g2.setCursor(20,25);
 }
  else {
  u8g2.setCursor(38,25); //rand copiat
 } 

  u8g2.println(vin,1);                        //Prints the voltage
  u8g2.setCursor(84,25); 
  u8g2.println(" V");

if ((temp<0)&& (abs(temp)<9.9)){
  u8g2.setCursor(28,60);  
  u8g2.println(temp,1);                       //Prints the temperature
  u8g2.drawCircle(87,40,4);
  u8g2.drawCircle(87,40,3);
  u8g2.println(" C ");  
 }
  else if (temp<0) {
  u8g2.setCursor(10,60);   
 }
 else if (temp>9.99){
 u8g2.setCursor(20,60);
 }
 else{
 u8g2.setCursor(38,60);  
 }
 u8g2.println(temp,1);                        //Prints the temperature
 u8g2.drawCircle(88,40,4);
 u8g2.drawCircle(88,40,3);
 u8g2.println(F(" C"));
} 

schematic v-t display v-t mem

olikraus commented 4 months ago

Did you add pull-up resistors to the I2C bus lines? If not, then maybe try this. 5K-10K should be ok. Another option would be to try the SW_I2C constructor (just to check whether this will remove the problem).

fratellos commented 4 months ago

Thank you very much for this quick reply! I added pull up resistors earlier today...so far so good, working fine for about 3 hours. I've never tried the SW-I2C builder. See my builds and the builders I used in the image.

incercari

fratellos commented 4 months ago

Update: the code is crashed, again ... after a couple of hours of running :( Unfortunately, I had the PC closed overnight and could not see if the temperature was still displayed in the serial monitor (note : the whole assembly was powered from a USB port ; but it also appears if I power it from another source, with a transformer, rectifier bridge, 7805 regulator, decoupling condenser on input/output).

olikraus commented 4 months ago

Indeed the question is, does't the display (serial output is still available) or the Arduino crash (no serial output any more).

For the display: This is a 3.3V controller, which often is connected to a 5V board only with some resistor dividers. To be on the safe side a proper level shifter (maybe a 74HC4050) might be better to connect the display.

fratellos commented 4 months ago

Thank you so much for your support ! The display is powered by 3v3 Arduino's pin ... Please suggest an example for SW_I2C constructor instruction... Tried something like this, but no result. U8GLIB_SH1106_128X64 u8g(4, 5);

fratellos commented 4 months ago

Update Using u8g2lib, the crash is faster ( a few dozen minutes or so) and the serial monitor stop !

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include "U8g2lib.h"     

#define ONE_WIRE_BUS 2 //Pin DS al senzorului DS18B20

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;

U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);   

int analogInput = 0;
float vout = 0.0;
float vin = 0.0;
float R1 = 100000.0; // resistance of R1 (100K)
float R2 =  10000.0; // resistance of R2 (10K) 
int value = 0;

double temp;

void setup() { 
  Serial.begin(38400);
  u8g2.begin();
  pinMode(analogInput, INPUT);
  sensors.begin();
  sensors.setResolution(tempDeviceAddress, 11);
}

void loop() {
u8g2.clearBuffer();
   value = analogRead(analogInput);
   vout = (value * 5.0) / 1024.0; 
   vin = vout / (R2/(R1+R2)); 

if (vin<0.09) {
  vin=0.0;//statement to quash undesired reading !
  }

sensors.requestTemperatures();
  float tempC = sensors.getTempCByIndex(0); 
  if (tempC != DEVICE_DISCONNECTED_C)
  {
    temp=tempC;
  }
  else
  {
    temp= 99.9;  //aici mesajul de eroare senzor !!!!
  }

u8g2.firstPage();
do
   {
    draw();
   }
while ( u8g2.nextPage() ); 
  Serial.print(tempC);
  Serial.print("  ;  ");
  Serial.print(vin, 2);
  Serial.println();   
delay(1000);

}

void draw(void)
{

  u8g2.setFont(u8g2_font_helvB24_tf);
  u8g2.drawRFrame(0, 30, 128, 32, 10);     // draws frame with rounded edges

if (vin>9.99) {
  u8g2.setCursor(20,25);
 }
  else {
  u8g2.setCursor(38,25); //rand copiat
 } 

  u8g2.println(vin,1);                        //Prints the voltage
  u8g2.setCursor(84,25); 
  u8g2.println(" V");

if ((temp<0)&& (abs(temp)<9.9)){
  u8g2.setCursor(28,60);  
  u8g2.println(temp,1);                       //Prints the temperature
  u8g2.drawCircle(87,40,4);
  u8g2.drawCircle(87,40,3);
  u8g2.println(" C ");  
 }
  else if (temp<0) {
  u8g2.setCursor(10,60);   
 }
 else if (temp>9.99){
 u8g2.setCursor(20,60);
 }
 else{
 u8g2.setCursor(38,60);  
 }
 u8g2.println(temp,1);                        //Prints the temperature
 u8g2.drawCircle(88,40,4);
 u8g2.drawCircle(88,40,3);
 u8g2.println(F(" C"));
} 

crash crash with u8g2

olikraus commented 4 months ago

The software emulated constructor should be:

U8G2_SH1106_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, clk_pin, data_pin, /* reset=*/ U8X8_PIN_NONE);   

The constructor names are all (!) listed here: https://github.com/olikraus/u8g2/wiki/u8g2setupcpp#communication

Did you also try to remove the OneWire sensor? I mean, just to ensure. that the problem is not caused by the temp sensor lib.

fratellos commented 4 months ago

Hi ! Thanks for reply ! If I remove the OneWire lib, the reason for this electronic assembly disappears... I can make just voltmeter, but...

olikraus commented 4 months ago

Sure... It's just for testing...

fratellos commented 4 months ago

"Using u8g2lib, the crash is faster ( a few dozen minutes or so) and the serial monitor stop !" So, I revert to U8G. This : U8G2_SH1106_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, clk_pin, data_pin, /* reset=*/ U8X8_PIN_NONE); is for U8G2 ! How look for U8G ?

olikraus commented 4 months ago

How look for U8G ?

oh, good question... I don't remember. I have not worked with U8G for almost 10 years. But if the problem happens with both U8G and U8G2, then I find it very unlikely that this is caused by the display lib. Can you be sure, that the issue is not caused by the OneWire / Sensor lib? To prove, that the temperature sensor doesn't cause the issue, I personally would replace the temperature result with a constant value and disable the sensor just to see, whether the problem is still there.

fratellos commented 4 months ago

With the U8G2 library, the blockage appears after a few minutes or tens of minutes. With U8G the blocking occurs much later (hours). What I did yesterday: I put 10k pull-up resistors right on the display pins and moved the display power supply (instead of connecting it to 3v3 of the Arduino board, I connected it directly to 5v from the stabilizer). The montage worked last night from 19:00 until 7:00 in the morning, without getting stuck (note, with U8G). I will do more tests at the weekend. I will also consider disabling OneWire. Thank you very much for the support!

fratellos commented 4 months ago

Partial conclusion :

olikraus commented 4 months ago

and yet...why another 10 K??

You need pull up resistors on both I2C bus lines.

https://learn.adafruit.com/working-with-i2c-devices/pull-up-resistors

fratellos commented 4 months ago

Aren't these the pull-up resistors ? They are connected to SCK and SCL

fratellos commented 4 months ago

pull_up

olikraus commented 4 months ago

maybe...

fratellos commented 4 months ago

LE ...the assembly works well after the last changes (with pull-up resistors and display power supply directly from 5 v). ... I tried this u8g2 option : seems to make the difference ! The code using 8g2 lib works fine from about 3 hours ! Thank you very much for the support! u9g2_busclock

fratellos commented 4 months ago

So far it has worked perfectly with the above additions. Thank you, Mr. Oliver, for a job so well done!

fratellos commented 4 months ago

I received another oled display ; it works just fine, with both libraries, without pull-up resistors or software mods....

good