Go Down

Topic: Question regarding ssd1306 and sensor details (using u8g2) (Read 2741 times) previous topic - next topic

david_prentice

#30
Sep 22, 2018, 12:04 am Last Edit: Sep 22, 2018, 12:05 am by david_prentice
Please post the complete program i.e. your current version.

Quite honestly,   your sensors should return the correct temperature values.    If they  work with the library example they should work with your OLED.

You can have many devices on the I2C bus.   You should always have external pullup resistors.   They are often mounted on breakout boards.   
Yes,   it s convenient to wire one device to A4, A5  and  the  other to SDA, SCL pins beause A4, A5 are I2C on a Uno.   You can find VCC, GND on the  power header  and also on the  3x2 ISP header.

But most importantly,   if  you have multiple I2C devices they must all use the same driver e.g. hardware I2C.    Your software I2C constructor will not work if you have other devices  uusing Wire.h library.

David. 

CatDadJynx

Ahh, I'm an idiot- I didn't know i2c required external pull up resistors, but after a quick Google search I certainly understand why. Having not used them I would think that would be the problem. I'll go ahead and get those set up as they should be and try again, then post my code saying if it worked or not.

Also, I remember earlier in the thread, olikraus said "For proper cooperation between multiple I2C devices on the same bus, you MUST use the HW I2C constructor."

So I already changed that. Will just do some more leg work and update. Sorry for the headache, thanks!

CatDadJynx

Hmm, alright... So I've wired up what I believe to be correct, and reuploaded two different programs, with the same results. I'll post both programs once I'm more confident my wiring is correct.

As for the pull up resistors, im using one 2.2k resistor tied into each sda and scl line (4 resistors total), going to each devices respective voltage supply (3.3 and 5v). I also have 2k and 1k, but I read the suggested range for most i2c devices (3.3 or 5v) is 1.8-2.7k, some saying as high as 4.7. I wasn't sure what would be best for either device though, as I don't have an oscilloscope to check the frequencies and try to calculate it myself (so I'm assuming it's 100khz, as seems to be the standard). Does this seem correct?

And the last thing I need to try (before im sure I have the wiring correct) is to get a power supply on my breadboard, just in case the USB power alone isn't enough to supply the correct voltage (as I also don't have multimeter to check).

olikraus

For the I2C bus you need only two resistors: One for SDA and one for SCK. One end of the resistor goes to the corresponding GPIO pin (SDA and SCK), the other end goes to the power supply. Which power supply this will be, depends on the desired I2C bus voltage. The I2C bus voltage in turn depends on the connected devices. 

Let me use the IR sensor. The Adafruit web page from here https://www.adafruit.com/product/1748 says:

Quote
This sensor comes in an easy-to-use metal can. You can easily solder it or plug it into a breadboard. The four pins are used for power, ground, i2c clock and i2c data. There are two versions, one for 3V power and logic levels and one for 5V power and logic levels. This item is the 5V version! - good for use by classic Arduinos. You'll also want two 10K pull-up resistors for the I2C data lines, which we thoughtfully include.
Keywords are: "5V power and logic level" and "10K pull-up resistors".

The same should be true for the SSD1306 OLED, so you can connect the OLED on the same bus.

Quote
going to each devices respective voltage supply (3.3 and 5v).
No, do not do this: Select one voltage level only (must be 5V if you own the 5V sensor).

Oliver

CatDadJynx

Ahh, thanks for clarifying. Yeah, at first I had both set to 5v, then realized that might have been wrong, so tried 3.3/5v. My setup was correct the first time, the values i was using were just much too low. Will try that here in a bit, thanks!

CatDadJynx

Okay, I tried the 10k but that didn't work either, but now I think I see where I went wrong. I found this wiring diagram for i2c pull ups, and i thought each device required their own resistors, but now I see everything is wired together to the same resistors. Which makes more sense, because I was seeing people saying the resistor values depended on total bus capacitance, now I see why and now I see why a stronger resistor fits in with that. I'm still a little unsure of my wiring though, just because my cables are a little long and I'm not sure how that may affect the bus capacitance, but im going to try to fix my setup now and that'll be a start.

I will also be turning a secondary Uno and oled into a makeshift voltmeter because I don't have a multimeter (so I will just do this using a simple analogRead to u8g2, because that's something I'll have to add to this project later anyway) but there are plenty of resources for that, so i won't bring that into this thread. Hopefully that will help me see my setup better though, too. Sorry for so many beginner questions/issues, but the help has gone a long way so far. Thanks!

CatDadJynx

Alas, still no luck. The wiring diagram in my last post is reflective of my current setup, using two 10K resistors. But now, both devices are going to the same SCL and SDA pins on the Arduino. Here are the two programs ive been trying each time (both yielding the same results).

Program 1:
Code: [Select]


/***************************************************
  This is a library example for the MLX90614 Temp Sensor

  Designed specifically to work with the MLX90614 sensors in the
  adafruit shop
  ----> https://www.adafruit.com/products/1748
  ----> https://www.adafruit.com/products/1749

  These sensors use I2C to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Wire.h>
#include <Adafruit_MLX90614.h>

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

Adafruit_MLX90614 mlx = Adafruit_MLX90614();
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

void setup() {
  u8g2.begin();
  u8g2.enableUTF8Print();
  mlx.begin();
}

void loop() {
  u8g2.clearBuffer();                                 // update
  u8g2.setFont(u8g2_font_5x7_tf);
  u8g2.setCursor(0, 15);
  u8g2.print("Ambient = "); u8g2.print(mlx.readAmbientTempC());
  u8g2.setCursor(0, 25);
  u8g2.print("*C\tObject = "); u8g2.print(mlx.readObjectTempC()); u8g2.println("*C");
  u8g2.setCursor(0, 35);
  u8g2.print("Ambient = "); u8g2.print(mlx.readAmbientTempF());
  u8g2.setCursor(0, 45);
  u8g2.print("*F\tObject = "); u8g2.print(mlx.readObjectTempF()); u8g2.println("*F");
  u8g2.println();
  u8g2.sendBuffer();
  delay(500);
}


Program 2:

Code: [Select]
#include <Wire.h>
#include <Adafruit_MLX90614.h>

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

Adafruit_MLX90614 mlx = Adafruit_MLX90614();

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

const long screenInterval = 1000;           // interval at which to buffer (milliseconds)
unsigned long sensorInterval = 500;
unsigned long screenPreviousMillis = 0;
unsigned long sensorPreviousMillis = 0;


void setup() {
  mlx.begin();
  u8g2.begin();
  u8g2.enableUTF8Print();
}


void loop()
{
  unsigned long sensorCurrentMillis = millis();
  static double oldAmbientC = 500;
  static double oldObjectC = 500;                     // retains values
  if (sensorCurrentMillis - sensorPreviousMillis >= sensorInterval) {
    sensorPreviousMillis = sensorCurrentMillis;             // for next read
    double AmbientC = mlx.readAmbientTempC();
    double ObjectC = mlx.readObjectTempC();
    double AmbientF = mlx.readAmbientTempF();
    double ObjectF = mlx.readObjectTempF();
    if (AmbientC != oldAmbientC || ObjectC != oldObjectC) { // ?changed
      oldAmbientC = AmbientC;                             // remember
      oldObjectC = ObjectC;
      u8g2.clearBuffer();                                 // update
      u8g2.setFont(u8g2_font_5x7_tf);
      u8g2.setCursor(0, 15);
      u8g2.print("Ambient = "); u8g2.print(AmbientC);
      u8g2.setCursor(0, 25);
      u8g2.print("*C\tObject = "); u8g2.print(ObjectC); u8g2.println("*C");
      u8g2.setCursor(0, 35);
      u8g2.print("Ambient = "); u8g2.print(AmbientF);
      u8g2.setCursor(0, 45);
      u8g2.print("*F\tObject = "); u8g2.print(ObjectF); u8g2.println("*F");
      u8g2.println();
      u8g2.sendBuffer();                                  // draw the screen
    }
  }
}


In the meantime i will be working on a way to measure voltage, so hopefully i can shed more light on my i2c setup.

PNOMBLOT

Hello,

I found the solution with MLX90614 giving always  1037.55 °C.
the problem looks to be due to the I2C clock speed, u8g2 set the highest I2C clock speed but MLX90614 does not work at 400KHz, so  add "u8g2.setBusClock(100000);" to slow down I2C to 100KHz


Here is a working full example code:


Code: [Select]
#include "TimeLib.h"
#include <Adafruit_MLX90614.h>
#include <U8g2lib.h>    // https://github.com/olikraus/u8g2/wiki/u8g2reference#reference


//******************************* OLED ***************************************
U8G2_SSD1306_64X48_ER_1_HW_I2C  u8g2(U8G2_R0);

//****************************** MLX90614 *************************************
Adafruit_MLX90614 mlx = Adafruit_MLX90614();


//******************************** VARS **************************************
time_t time;
unsigned long timer;
const char DEGRE_C[] = { 0xB0,'C', '\0' };


void setup() {
  mlx.begin(); 
  u8g2.setBusClock(100000);
  u8g2.begin();
  Serial.begin(115200);
  u8g2.setFont(u8g2_font_unifont_t_symbols);
}

void loop() {
  timer = millis(); 
  Serial.print("Ambient = ");  Serial.print(mlx.readAmbientTempC()); Serial.print("°C");
  Serial.print("\tObject = "); Serial.print(mlx.readObjectTempC());  Serial.println("°C");

  u8g2.firstPage();
  do { 
      u8g2.setCursor(0,12);
      u8g2.print(mlx.readAmbientTempC()); u8g2.print(DEGRE_C);
      u8g2.setCursor(0,32);
      u8g2.print(mlx.readObjectTempC()); u8g2.print(DEGRE_C);
  } while( u8g2.nextPage() );

   while (millis() < (timer + 300)) {
     delay(5);
  }

}

Go Up