How to use two sensors in one board

Hi. I want to make two sensors work on one board. I use UNO R4 minima and mlx90614 and BMP280.

For I2C, there is only one set of SDA/SCK(A4 and A5), I have to use both sensors in one set but I can't find how to make a code with a parallel circuit.

As SPI, I already use my d11,12,13 pin. So I want to make another dig pin as MISO, MOSI, SCK and use them, but I can't find how to do so.

Regardless of the method, I wish I could receive two sensor values โ€‹โ€‹from one board.......
I am sooo newbie to this and my head is really confused now. My search skill now reach the limit......... I desperately need your help. What should I do? Any answer will be very helpful.

Thanks.

I think that you have got SPI and I2C reversed in your description

Both are bus configurations, so multiple devices can be connected to the same pins.

The device to read from or write to is then defined by an address in the case of I2C or a SS (select) pin for each device in the case of SPI

I agree, you got SPI and i2c mixed up there!

mlx90614 seems to have an i2c interface.

BMP280 can have either SPI or i2c, but many breakout modules allow only i2c. But that's fine.

I recommend using i2c for both. Connect them to the same pins. The two devices have different addresses. Probably the Arduino libraries you will use with them will take care of the addressing for you. It should be easy.

are you thinking that you need a duplicate set of pins?
don't the devices have different addresses?

Can I get a example code's link? I have no idea what to do...

This is my full code:

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_MLX90614.h>
#include "RTC.h"
#include "DHT.h"
#include <SD.h>

File myFile;

Adafruit_MLX90614 mlx = Adafruit_MLX90614();
Adafruit_BMP280 bmp;

void setup() {
  Serial.begin(9600);
  while ( !Serial ) delay(100);   // wait for native usb
  unsigned status;
  status = bmp.begin();

  /* Default settings from datasheet. */
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
  float seaLevelPressure = 1014.3;

  mlx.begin();  

}

void loop() {

 // BMP
    myFile.print(F("Pressure = "));
    myFile.print(bmp.readPressure()/100);
    myFile.print(" hPa  ");

    myFile.print(F("Approx altitude = "));
    myFile.print(bmp.readAltitude(1014.3));
    myFile.println(" m");


    myFile.print("Ambient = "); 
    myFile.print(mlx.readAmbientTempC()); 
  
    myFile.print("ยฐC  Object = ");
    myFile.println(mlx.readObjectTempC()); Serial.println("ยฐC");
    //mlx

    myFile.println();
    myFile.close(); // ํŒŒ์ผ์„ ๋‹ซ์Šต๋‹ˆ๋‹ค.
  } else {
    // ํŒŒ์ผ์ด ์—ด๋ฆฌ์ง€ ์•Š์œผ๋ฉด ์—๋Ÿฌ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    Serial.println("error opening test.txt");
  }
  delay(5000); // 5์ดˆ ๋Œ€๊ธฐ
}

What should I do here?

Well... if you use i2c for both sensors like I suggested, you won't need the SPI library.

Your code does not seem to use an RTC, so perhaps you don't need that library either.

You seem to be using the DHT library, but there is no code in your sketch for that either. DHT sensors can measure humidity, which BMP280 cannot, but if you had chosen BME280, there would be no need for the DHT sensors also because BME280 can measure temperature, humidity and pressure.

actually, my project is using DHT and BMP and RTC and mlx at once.
I post part of it cause I think It won't be necessary to upload it.

Here is entire code:

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_MLX90614.h>
#include "RTC.h"
#include "DHT.h"
#include <SD.h>

File myFile;

#define DHTPIN 7     // Digital pin connected to the DHT sensor
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.
// DHT ์„ค๋ช…์€ DHT tester ์ฐธ๊ณ 

#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
Adafruit_BMP280 bmp;

void setup() {
  Serial.begin(9600);
  while ( !Serial ) delay(100);   // wait for native usb
  unsigned status;
  status = bmp.begin();

  /* Default settings from datasheet. */
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
  float seaLevelPressure = 1014.3;
  //์—ฌ๊ธฐ๊นŒ์ง€ ๊ธฐ์••์„ผ์„œ


  // ์˜จ๋„ ์„ผ์„œ ์‹œ์ž‘
  mlx.begin();  


  RTC.begin();
  // ์‹œ๊ฐ„ ์„ค์ •
  RTCTime startTime(9, Month::SEPTEMBER, 2023, 00, 00, 00, DayOfWeek::SATURDAY, SaveLight::SAVING_TIME_ACTIVE);
  RTC.setTime(startTime);
  //์—ฌ๊ธฐ๊นŒ์ง€ ์‹œ๊ฐ„์„ค์ •


  dht.begin();
  //dht ์‹œ์ž‘

  if (!SD.begin(4)) { // SD์นด๋“œ ๋ชจ๋“ˆ์„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
    Serial.println("initialization failed!"); // SD์นด๋“œ ๋ชจ๋“ˆ ์ดˆ๊ธฐํ™”์— ์‹คํŒจํ•˜๋ฉด ์—๋Ÿฌ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    while (1);
  }
  Serial.println("initialization done.");

}

void loop() {

  myFile = SD.open("log.txt", FILE_WRITE);

  RTCTime currentTime;

  // ํ˜„์žฌ์‹œ๊ฐ„ ๋ฐ›์•„์˜ค๊ธฐ
  RTC.getTime(currentTime);
  
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();

  if (myFile) { // ํŒŒ์ผ์ด ์ •์ƒ์ ์œผ๋กœ ์—ด๋ฆฌ๋ฉด ํŒŒ์ผ์— ๋ฌธ์ž๋ฅผ ์ž‘์„ฑ(์ถ”๊ฐ€)ํ•ฉ๋‹ˆ๋‹ค.
    myFile.print(currentTime.getHour());
    myFile.print(":");
    myFile.print(currentTime.getMinutes());
    myFile.print(":");
    myFile.println(currentTime.getSeconds());
    // ์—ฌ๊ธฐ๊นŒ์ง€ ์‹œ๊ฐ„


    myFile.print(F("Pressure = "));
    myFile.print(bmp.readPressure()/100);
    myFile.print(" hPa  ");

    myFile.print(F("Approx altitude = "));
    myFile.print(bmp.readAltitude(1014.3)); //ํ˜„์žฌ๊ธฐ์••
    myFile.println(" m");
    //์—ฌ๊ธฐ๊นŒ์ง€ ๊ธฐ์••


    // ์ฃผ๋ณ€ ์˜จ๋„๋ฅผ ์„ญ์”จ๋กœ ์ถœ๋ ฅ
    myFile.print("Ambient = "); 
    myFile.print(mlx.readAmbientTempC()); 
  
    // ๋Œ€์ƒ ์˜จ๋„๋ฅผ ์„ญ์”จ๋กœ ์ถœ๋ ฅ
    myFile.print("ยฐC  Object = ");
    myFile.println(mlx.readObjectTempC()); Serial.println("ยฐC");
    //์—ฌ๊ธฐ๊นŒ์ง€ mlx


    myFile.print(F("Humidity: "));
    myFile.print(h);
    myFile.print(F("%  Temperature: "));
    myFile.print(t);
    myFile.println(F("ยฐC "));
    //์—ฌ๊ธฐ๊นŒ์ง€ dht

    myFile.println();
    myFile.close(); // ํŒŒ์ผ์„ ๋‹ซ์Šต๋‹ˆ๋‹ค.
  } else {
    // ํŒŒ์ผ์ด ์—ด๋ฆฌ์ง€ ์•Š์œผ๋ฉด ์—๋Ÿฌ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    Serial.println("error opening test.txt");
  }
  delay(5000); // 5์ดˆ ๋Œ€๊ธฐ
}

//๊ธฐ์•• I2C ์—ฐ๊ฒฐ, scl -> a5, sda -> a4
//์—์Šค๋”” vcc -> 5v , MISO -> d12 , MOSI -> d11 , SCK -> d13 , CS -> d4
//dht nc -> x , dat -> dig 7 , vcc -> 5v

What is wrong with this code?

Also, sorry, of course you will need the SPI library for the SD library to work.

Hi, @euns1216

Did you start with code for each individual peripheral?
To get code that works and is bug free for each sensor?
Before combining them all?

If not then leave your full code for the moment, and write separate bits of code for each sensor and prove you can communicate with them.

Thanks... Tom.. :grinning: :+1: :coffee: :australia:

You seem to be a real beginner.

As a real beginner if you put together code that uses more than one sensor before even starting testing. In your case you are using

  1. MLX
  2. BMP
  3. RTC
  4. SD card
  5. DHT

There are not only 4 places where a bug could be there are
4 * 4 * 4 * 4 * 4 = 1024 places where a bug could be.
Now estimate how long does it take to test your complete code until you have tested for 1024 potential bugs?

It is well invested time to save a lot of time to develop code in small steps.
Where you write a testcode for one component and immidiately test if this one component works.

If this works add a second component and do the same procedure again.

Your project will be up and running 3 times faster if you develop your code this way step by step

So with which component to do want to start?

best regards Stefan

1 Like

You got a point there, and it's a (common?) mistake for newcomers to go for more than they can chew.

A good thing I do more of lately (I'm a real beginner too), is to put code in different pages / tabs. Helps a LOT.

Don't worry, he'll catch up :slight_smile:

From experience here, putting code in multiple tabs causes more problems than it solves unless you really know what you are doing

1 Like

There is one step about making each piece then combining them.

What works One Thing At A Time by forcing delays/wait-for's will have to be changed to only make itself wait, it takes practice to really get

  1. understanding what blocks smooth, timely execution of void loop().
  2. knowing the code techniques to unblock execution.

And then the sketches can combine and name/resource clashes be resolved.

I2C can take around 80-100 ms to get a response to a request, I know from millis-stamped log lines. Read characters as they arrive, don't wait for whole transmissions but rather monitor many in the same period.
When you don't block, it's possible without stretching an Uno.

1 Like

I find the overview with tabs feel I'm in charge of the code. Sure there's a limit where it goes out of hand as well, to put all blocks of code in their own tabs won't do any good.

How do you get a good overview over the code yourself?

How does this (not my work) look? It is for beginners with some experience.

There is one more lesson to combine with do many things at once (watch a burron and blink a led) and that lets a process be done as steps small enough to not block and able to be finished over many loop() runs.

Think of void loop() as a wheel. Every time it goes around some time passes and some steps of multiple tasks get done even if the step is to not be triggered and not do something yet. Just rolling along, that's automation.

The first step is to use sensible function names so that their purpose is more obvious. Secondly functions should do one thing rather than several, even if that means having more functions. Most, functions of the sketch when running are called from loop() so that becomes the point of reference. Thus loop() calls the functions in a particular order which defines the structure of the sketch

Of course, none of the above precludes the use of tabs , but because IDE 2.x allows you to easily jump to a function or variable definition whether they are in separate tabs or in the main .ino file does not really matter. As an extension to this, it does not matter whether the function that you want to see is part of your own sketch or in a library #included in it, you can jump to it in the same way

1 Like

1.x tabs had some weird compile twist, IIRC was Java related.

I hadn't thought but with 2.x can source .c or .cpp files #include as if typed in there where I want? And not have to extern vars? Combine code (but not the .ino) without copy and paste or making everything a library?

That can be workable. It's code-toolbox-friendly at the filename level.

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