I2C + 1-Wire ok, add another 1-Wire and nothing works

Hi,

Can Arduino Nano have 2 x 1-Wire?

A have an Arduino Nano with 20 x DS18B20 (temperature sensor) connected via 1-Wire. A SSD1306 display connected via I2C.

Every 5 sec Arduino reads 3 sensors and show in the display. Very often the Arduino don´t read 1 or 2 sensors.

My solution was to create 2 diferent 1-Wire communication. I connected 12 sensors in Com1 and 8 sensors in Com2.

After a added the second 1-wire, everything wents crazy! The button didn´t work, arduino start to reset....

I start to delete everthing to find the problem.

The problem appears when I added this segment:

 #define DS18B20_OneWire2 6     //pino 2
OneWire oneWire2(DS18B20_OneWire2);
DallasTemperature sensortemp2(&oneWire2);

If I run the program only with Com1 it´s ok, any line with com2 need to be comment.

If I run the program only with Com2 it´s ok, any line with com1 need to be comment.

My code

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);

//display
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
#if (SSD1306_LCDHEIGHT != 64)
#error("Ad_SSD1306.h!")
#endif

//sensores ds18b20
#define DS18B20_OneWire 2     //pino 2
OneWire oneWire(DS18B20_OneWire);
DallasTemperature sensortemp(&oneWire);

#define DS18B20_OneWire2 6     //pino 6
OneWire oneWire2(DS18B20_OneWire2);
DallasTemperature sensortemp2(&oneWire2);

// Endereço dos sensores DS18B20 - ALTERAR DE ACORDO COM SEU PROJETO
uint8_t s1_X[8] =                   { 0x28, 0x5A, 0x90, 0x44, 0xD4, 0xE1, 0x3C, 0x8D }; // x    
uint8_t s2_Yd[8] =                  { 0x28, 0xDE, 0x2E, 0x45, 0xD4, 0xFE, 0x6B, 0x75 }; // yd
uint8_t s3_Ye[8] =                  { 0x28, 0x4B, 0xBF, 0x45, 0xD4, 0xBF, 0x67, 0xA9 }; // ye
uint8_t s4_Z[8] =                   { 0x28, 0xDE, 0xF0, 0x45, 0xD4, 0xEF, 0x6F, 0xC0 }; // z
uint8_t s5_Spind[8] =               { 0x28, 0xED, 0xDA, 0x44, 0xD4, 0xE1, 0x3C, 0x5B }; // spindle
uint8_t s6_VFD[8] =                 { 0x28, 0xA0, 0x69, 0x82, 0x00, 0x00, 0x00, 0x7E }; // interno
uint8_t s7_Filtro_48V_1[8] =        { 0x28, 0x11, 0x47, 0x45, 0xD4, 0xE4, 0x14, 0x9E }; // 
uint8_t s8_Filtro_48V_2[8] =        { 0x28, 0x93, 0x17, 0x45, 0xD4, 0xB1, 0x0F, 0xBA }; // 
uint8_t s9_Filtro_24V_Controle[8] = { 0x28, 0x36, 0x50, 0x45, 0xD4, 0xDD, 0x67, 0x05 }; // 
uint8_t s10_Filtro_24V_Sinal[8] =   { 0x28, 0x24, 0x3F, 0x45, 0xD4, 0x6D, 0x6F, 0x8E }; // 
uint8_t s11_Fonte_5V[8] =           { 0x28, 0x53, 0x76, 0x45, 0xD4, 0xA9, 0x1D, 0x42 }; // 
uint8_t s12_Fonte_24V_Controle[8] = { 0x28, 0xCC, 0x5E, 0x45, 0xD4, 0xC2, 0x7A, 0x8E }; // 
uint8_t s13_Fonte_24V_Sinal[8] =    { 0x28, 0x9C, 0x3E, 0x45, 0xD4, 0xB0, 0x20, 0x33 }; // 
uint8_t s14_Fonte_12V[8] =          { 0x28, 0x34, 0x22, 0x45, 0xD4, 0xAF, 0x7D, 0x41 }; // 
uint8_t s15_Fonte_48V_1[8] =        { 0x28, 0xCC, 0x5E, 0x45, 0xD4, 0xC2, 0x7A, 0x8E }; // 
uint8_t s16_Fonte_48V_2[8] =        { 0x28, 0x9E, 0xCD, 0x45, 0xD4, 0x0E, 0x67, 0xAE }; // 
uint8_t s17_Xdr[8] =                { 0x28, 0xC0, 0xCB, 0x82, 0x00, 0x00, 0x00, 0x0D }; // 
uint8_t s18_Yddr[8] =               { 0x28, 0xA3, 0x93, 0x44, 0xD4, 0xE1, 0x3C, 0x27 }; // 
uint8_t s19_Yedr[8] =               { 0x28, 0x23, 0x90, 0x45, 0xD4, 0xC5, 0x41, 0xF3 }; // 
uint8_t s20_Zdr[8] =                { 0x28, 0x80, 0xF6, 0x45, 0xD4, 0x4E, 0x44, 0x48 }; // 

//variavel do programa
const byte Bt_Selecao = 3;
const byte Buzzer = 4;
const byte Bt_Pausa = 5;
byte Tela = 0;
byte Temp_5 = 0;
byte Selecao = 0;
byte Pausa = 0;
int Vl_Temperatura_Sensor[21]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte Contagem_Erro[21] =      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

//Funcoes
void mostrar_temp();
void valortemperatura(DeviceAddress deviceAddress, byte Inc_Temperatura_Sensor); 

//Interrupcao
ISR(TIMER1_OVF_vect)                              //interrupção do TIMER1 
{
  TCNT1 = 0xC2F7;                                 // Renicia TIMER
  Temp_5++;
  if (Temp_5 >= 5)
  {
    Temp_5 = 0;
    Tela ++;
    mostrar_temp();
    if (Tela >= 7) Tela = 0;
  }//end if
}//end Interrupcao

void setup()   {                
  Serial.begin(57600);
  pinMode(Bt_Selecao, INPUT_PULLUP);
  pinMode(Buzzer, OUTPUT);
  digitalWrite(Buzzer, 0);
  pinMode(Bt_Pausa, INPUT_PULLUP);

  //Configuracao da Interrupcao
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1B |= (1<<CS10)|(1 << CS12);  //base 1024
  TCNT1 = 0xC2F7;   // 1 seg
  TIMSK1 |= (1<< TOIE1);    //habilita Int

  //iniciar display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)

  // Clear the buffer.
  display.clearDisplay();
  display.display();

  //iniciar sensor ds18b20 
  sensortemp.begin(); 
// sensortemp2.begin(); 

  //tabela de characteres com º (graus)
  display.cp437(true);
  mostrar_temp();
}//end Setup

void loop() 

{
  Selecao = digitalRead(Bt_Selecao);
  Pausa = digitalRead(Bt_Pausa);

  if(Selecao == 0)
  {
    Tela ++;
    if (Tela > 7) Tela = 1;
    TCNT1 = 0xC2F7; 
    mostrar_temp();
    delay(300);
  }

  if(Pausa == 0)
  {
    TIMSK1= 0;    //desabilita Int
    digitalWrite(Buzzer, 0);
    TCNT1 = 0xC2F7;  
    mostrar_temp();
    delay(300);
  }//end if
  else
  {
   TIMSK1= 1;
  }
}//end Loop

void mostrar_temp()
{
  sensortemp.requestTemperatures();
  display.clearDisplay();  
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.print(F(" CABlue  "));
  display.println(Tela);

  switch (Tela)  {
    case 0:
    // Tela inicial
      display.println(F("MMSA"));
      display.println(F("v3.1"));
      display.println(F("03/2026"));
    break;

    case 1:
      display.print(F("X    :"));
      valortemperatura(s1_X,1);
      display.print(F("Yd   :"));
      valortemperatura(s2_Yd,2);
      display.print(F("Ye   :"));
      valortemperatura(s3_Ye,3);
    break;

    case 2:
      display.print(F("Z    :"));
      valortemperatura(s4_Z,4);
      display.print(F("Spind:"));
      valortemperatura(s5_Spind,5);
      display.print(F("VFD  :"));
      valortemperatura(s6_VFD,6);
    break;

    case 3:
      display.print(F("5V   :"));
      valortemperatura(s11_Fonte_5V,11);
      display.print(F("12V  :"));
      valortemperatura(s14_Fonte_12V,14);
      display.print(F("24Vc :"));
      valortemperatura(s12_Fonte_24V_Controle,12);
    break;

    case 4:
      display.print(F("24Vcf:"));
      valortemperatura(s9_Filtro_24V_Controle,9);
      display.print(F("24Vs :"));
      valortemperatura(s13_Fonte_24V_Sinal,13);
      display.print(F("24Vsf:"));
      valortemperatura(s10_Filtro_24V_Sinal,10);
    break;

    case 5:
      display.print(F("48V1 :"));
      valortemperatura(s15_Fonte_48V_1,15);
      display.print(F("48v1f:"));
      valortemperatura(s7_Filtro_48V_1,7);
      display.print(F("48V2 :"));
      valortemperatura(s16_Fonte_48V_2,16);
    break;

    case 6:
      display.print(F("48V2f:"));
      valortemperatura(s8_Filtro_48V_2,8);
      display.print(F("Xdr  :"));
      valortemperatura(s17_Xdr,17);
      display.print(F("Yddr :"));
      valortemperatura(s18_Yddr,18);
    break;

    case 7:
      display.print(F("Yedr :"));
      valortemperatura(s19_Yedr,19);
      display.print(F("Zdr  :"));
      valortemperatura(s20_Zdr,20);
    break;
  } //end switch
  display.display();
}//end

//funcao para mostrar o valor da temperatura corretamente
void valortemperatura(DeviceAddress deviceAddress, byte Inc_Temperatura_Sensor)  
{
  float grausC = sensortemp.getTempC(deviceAddress);

  if (grausC < 0) //erro de medida
  {
    Contagem_Erro[Inc_Temperatura_Sensor]++;
    if (Contagem_Erro[Inc_Temperatura_Sensor]>=10)
      {
        display.print(F("Erro")); 
        display.println();
      }//end if
    else
      {
        display.print(Vl_Temperatura_Sensor[Inc_Temperatura_Sensor]); 
        display.write(0xF8);
        display.println(F("C"));
      }//end else Contagem de Erro
  }//end if

  if (grausC >= 0 && grausC < 80) //Medida Correta
    {
    Vl_Temperatura_Sensor[Inc_Temperatura_Sensor] = grausC;
    display.print(Vl_Temperatura_Sensor[Inc_Temperatura_Sensor]); 
    display.write(0xF8);
    display.println(F("C"));
    digitalWrite(Buzzer, 0);
    Contagem_Erro[Inc_Temperatura_Sensor]=0;
    }

  if (grausC >= 80) //Medida Correta
    {
    Vl_Temperatura_Sensor[Inc_Temperatura_Sensor] = grausC;
    display.print(Vl_Temperatura_Sensor[Inc_Temperatura_Sensor]); 
    display.write(0xF8);
    display.println(F("C"));
    digitalWrite(Buzzer, 1);
    Contagem_Erro[Inc_Temperatura_Sensor]=0;
    }
}//end valortemperatura

When you compile, you should gen an output something like this:

Sketch uses 10336 bytes (33%) of program storage space. Maximum is 32768 bytes.
Global variables use 874 bytes (42%) of dynamic memory, leaving 1174  bytes for local variables. Maximum is 2048 bytes.

How many bytes and % of "dynamic memory" do your Global variables use and how many bytes/% do you have left when using one 1-wire definition? When using both 1-wire definitions?

Your arrays take some 224 bytes of memory. You also have an OLED display which probably takes 1k of buffer space and then two OneWire objects. The Nano has only 2k of SRAM to play with so I am wondering whether its rather tight and running out of runtime memory, which will lead to weird problems including crashing and re-starting.

Your code uses a deprecated constructor for Adafruit_SSD1306. That alone raises concerns about the rest of the code.

When compiled, your code uses 824 bytes of RAM. Add in the 1K of RAM that the SSD1306 library will allocate at runtime, and you're now at 90% of RAM, before any local variables. And, that raises concerns.

Variables used by your ISR and also referenced by non ISR code are not declared volatile. That also raises concerns.

Your ISR calls a routine that displays to your OLED. No. NO. NO. That doesn't raise concerns, that's a huge, massive red flag.

I didn't even look that far, but yes, calling your mostrar_temp() function from within the ISR? Not a good idea. ISR functions should be very short, just setting a variable or flag. The rest, such as printing results needs to happen within the main loop.

Your schematic shows 5 volts applied to VIN pin, needs at least 6.5V for 5V regulator output.

ISR fixed:

ISR(TIMER1_OVF_vect)                              //interrupção do TIMER1 
{
  TCNT1 = 0xC2F7;                                 // Renicia TIMER
  Temp_5++;

  if (Temp_5 >= 5)
  {
    Temp_5 = 0;
    Tela ++;
    Estouro_ISR = 1;                    //ADDED
    if (Tela >= 7) Tela = 0;
  }//end if
void loop()
{
Selecao = digitalRead(Bt_Selecao);
Pausa = digitalRead(Bt_Pausa);

if (Estouro_ISR ==1)
{
mostrar_temp();
Estouro_ISR=0;
}.....

I didn´t know the Adafruit_SSD1306 was deprecat. Which library do you suggest to use?

There is little difference in the variables:
Before ISR change:

image

After ISR Change
image

My code has about 300 lines, and a space/jump a lot. Why is it using 88% of dynamic memory?

All the sensors are connected direct to 5V power supply.
I´ll change the Voltage input to pin 27 (+5V).

That's not what I wrote. I wrote that the constructor was deprecated.

I also wrote that the SSD1306 library would attempt to allocate 1K of RAM at runtime.

Add that to the space your global variables now take and think about whether or not you have enough RAM.

I´m using with 1x1-wire:

image

With 2 x 1-Wire

What can I do to reduce the global Variables?

I made the same code with only 1 sensor address . The global variables changed to 80%.
Still a lot! I don´t see who is taking all that memory!

Update:
The LCD/I2C uses abous 75% of the memory.

image

What do you mean:that the constructor was deprecated?

I shopuld use
Adafruit_SSD1306 display(126,68,OLED_RESET);

I mean the constructor was deprecated.

  // DEPRECATED CONSTRUCTORS - for back compatibility, avoid in new projects
  Adafruit_SSD1306(int8_t mosi_pin, int8_t sclk_pin, int8_t dc_pin,
                   int8_t rst_pin, int8_t cs_pin);
  Adafruit_SSD1306(int8_t dc_pin, int8_t rst_pin, int8_t cs_pin);
  Adafruit_SSD1306(int8_t rst_pin = -1);

Thank you everybody for helping me!

The problem was solve moving mostrar_temp() function from ISR.

Lately, I’ve been seeing more and more often that people asking questions are marking their own post as the solution. That’s not how it’s meant to work. The post that was most helpful should be marked as the solution. (You can still give the other helpers a heart as a thank you :wink:.)

Fixed!

If you are using the display to write text only, then you might consider using SSD1306Ascii library. If graphics are required then the U8g2 library. Both have a significantly smaller memory footprint then the default SSD1306 library. Each has specific limitations but may be adequate for your purposes.

If its working fine now then great, but you will probably have very little headroom for further developments, in which case one of the above options may help.

It really reduces the memory usage.