text:
Convert byte* to int in Arduino
I am trying to convert byte* value to int here is how I have it.
void mqttCallback(char* topic, byte* payload, unsigned int length) {

  String topicStr = topic;
  int* payload_value;
  int updates_cal;

    payload_value = (int*)payload;
    //updates_cal = *payload_value;

    Serial.print((int)payload_value);

  delay(1);

  Serial.println();
  Serial.println("-----------------------");

}

I am getting MQTT payload as Integer value. Which I want to receive in my NodeMCU (ESP8266).
Is there any way to do this?
Thank you!

If you want to convert a byte * to int, then you already have it, assuming that int is large enough to store an address on your platform. But what would be the point of this? Your payload_value is an address.

@AnT I just want integer (without pointer). How can I Serial.print it?

What specific integer do you want? Taken from where?

@AnT the integer is published by MQTT as a message.

The description of the format of MQQT message suggest that the second part of my answer (as well as Duncan C's) answer is the proper way to do it.

I tried that but its throwing error. Here is how the error looks like:

Exception (9):
epc1=0x40202430 epc2=0x00000000 epc3=0x00000000 excvaddr=0x3ffeeb79 depc=0x00000000

stack>>>

 ets Jan  8 2013,rst cause:4, boot mode:(1,6)

Considering the lengthy comments in the accepted answer, please consider editing this questions and / or title to reflect a more clear statement of what was desired.

Judging by the comments, you are actually receiving your integer data as text, as a sequence of ASCII characters. This is what you send yourself using mosquitto_pub. The buffer is apparently not zero-terminated.
If these characters represent an integer value, then the way to retrieve it as an integer value would be
char buffer[128];

// Make sure here that `length` is smaller than the above buffer size.
// Otherwise, you'd need a bigger buffer

// Form a C-string from the payload
memcpy(buffer, payload, length);
buffer[length] = '\0';

// Convert it to integer
char *end = nullptr;
long value = strtol(buffer, &end, 10);

// Check for conversion errors
if (end == buffer || errno == ERANGE)
  ; // Conversion error occurred
else
  Sterial.println(value);

Another approach, which avoids using a separate large[ish] buffer just for the purposes of zero-termination, would be
// Build a `scanf` format string that will read no more than `length`
// characters without relying on zero-termination of the payload
char format[16];
snprintf(format, sizeof format, "%%%ud", length);

// Convert the payload
int payload_value = 0;
if (sscanf((const char *) payload, format, &payload_value) == 1)
  Serial.println(payload_value);
else
  ; // Conversion error occurred

However, this approach is less protected from integer overflow than the previous one.

Note that most of the above "jumping through the hoops" is dedicated to adding a zero-terminator to the input buffer. If instead you opt for ensuring zero-termination on the sender's side, then it would all reduce to a simple
// Convert C-string to integer
char *end = nullptr;
long value = strtol((const char *) payload, &end, 10);

// Check for conversion errors
if (end == buffer || errno == ERANGE)
  ; // Conversion error occurred
else
  Sterial.println(value);

No extra buffers required.

Comments are not for extended discussion; this conversation has been moved to chat.

Don't know if you found an answer yet, but I had the exact same issue and eventually came up with this:
   payload[length] = '\0'; // Add a NULL to the end of the char* to make it a string.
   int aNumber = atoi((char *)payload);

Pretty simple in the end!

Keep in mind that payload[length] is not part of the memory dedicated to the payload variable. The last item in the memory space of an array always is length-1. Your approach may work most of the time, but you could potentialy overwrite other variables located at that place in memory.

byte* means "pointer to byte(s). It is usually used to point to a byte buffer, and usually will also have a length value so you know how many bytes are in the buffer. It looks like your function does have a length value.
If you're certain that the data in the payload parameter is a single int, and the length is correct for an int (2 bytes on Arduino I believe) then you should be able to cast the pointer to int* type and then fetch the value from the buffer:
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String topicStr = topic;
  int payload_value;
  int updates_cal;

  if (length >= 2) {
    //Cast payload to an int pointer and fetch the value
    intValue = *((int*)payload);
  }
}

I tried this, but there is some error. Its resetting my NodeMCU. Exception number is 9 is througing.


text:
Deep Sleep NodeMCU with Door Sensor
I have a very simple code of door sensor (magnetic) which gives results in 1 & 0 format. But I want to run the NodeMCU only when a door is open or close. Rest of time I want to keep it in deep sleep mode. Here is my code looks like :
int doorClosed = 1;

#define REED_SWITCH D5

void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);
  pinMode(BUILTIN_LED, OUTPUT);
  digitalWrite(BUILTIN_LED, HIGH);

  pinMode(REED_SWITCH, INPUT_PULLUP);
}

void loop() {
  // put your main code here, to run repeatedly

   Serial.println(digitalRead(REED_SWITCH));

    if ((digitalRead(REED_SWITCH) == HIGH) && (doorClosed == 1))
    {
      Serial.println("DOOR OPEN!!");
      doorClosed = 0;
      digitalWrite(BUILTIN_LED, LOW);
      ESP.deepSleep(0);
    }
    else if ((digitalRead(REED_SWITCH) == LOW) && (doorClosed == 0))
    {
      Serial.println("DOOR CLOSED!!");
      doorClosed = 1;
      digitalWrite(BUILTIN_LED, HIGH);
      ESP.deepSleep(0);
    }
    delay(500);
}

Here I am able to put the NodeMCU in deep sleep. But it never wakes up. How can I wake up my chip. After attaching the D0 with RST, I don't event get Serial Logs. I am not sure what kind of behaviour is this. If someone can help me to fix this code will be great!
Thank you!

According to this guide (https://randomnerdtutorials.com/esp8266-deep-sleep-with-arduino-ide/) the pin to be connected to RST is D0 and not A0.

I am sorry it was a typo mistake. I just fixed it.

After going in sleep mode, check D0 voltage value with a multimeter. Should be approximately to 0V.

If D0 is not 0V, connect RST to GND and check if microcontroller wakes up.

I just check the D0 voltage, but seems like its not going to 0V its showing me 3.25V. Which means its not going to deep sleep?
in multimeter I am touching D0 and GND pin to check the voltage.

Before investigating why D0 is high, try to connect GND to RST pin e check if arduino wakes up. ESP8266 documentation says that is sufficient a low value on RST pin to wakes up.

@leoc7 yes it was waking it up. But i am not able to see any details in serial monitor, so not sure how can i do that.

You can’t see any details on serial monitor because esp8266 restarts program and you have to re-open serial monitor. Use a led instead print on serial.

According to this guide:

The RST pin of the ESP8266 is always HIGH while the ESP8266 is
  running. However, when the RST pin receives a LOW signal, it restarts
  the microcontroller.
If you set a Deep Sleep timer with the ESP8266, once the timer ends,
  GPIO 16 sends a LOW signal. That means that GPIO 16 when connected to
  RST pin can wake up the ESP8266 every time the timer ends.

The only way to wakes up ESP8266 from deep sleep mode without timer is set a LOW signal on RST pin.
Example without timer:
ESP.deepSleep(0);

Connect D0 (GPIO 16) to RST is available only when ESP8266 is in sleep mode with timer.
Example with 30sec timer:
ESP.deepSleep(30e6);

In your case, you can use deep sleep with timer and connect Door sensor to D0 and will act as switch between the RST and D0.

can i do that programmatically?

also if its in deep sleep mode. Then how can i send a signal to it? i am using door sensor, will it be able to read its value in deep sleep?

You can’t do it programmatically! During deep sleep esp8266 is switched off and can’t do any operation. An approach can be to set a deep sleep mode with timer (e.g. 30sec) and connect D0 to RST. Every 30sec esp8266 wakes up, restart program and check door sensor.

interrupt will also not work in this case?

No, if you use Deep Sleep, ESP8266 is off and the only way to wake up it is trigger physically RST pin. Consider to use other type of sleep mode (for example light-sleep)
Take a look to this guide: https://www.losant.com/blog/making-the-esp8266-low-powered-with-deep-sleep

OK if I use door sensor then? Because door sensor can work externally on door open and close. As I want to connect with door sensor.

I got it working! Door sensor can be connected to D0 and will act as switch between the RST and D0. With this try. I am able to get it fixed. If you want you can post it under answer I will mark it right. :)

I modified the answer :) If you want you can mark as resolved.

i got it resolved upto a certain limit. The thing is i am able to restart it by setting the value high, but on closing door i don't get it restarted, so there is some challenge now

My response is late but herewith my experience that may be of help to others.
NodeMcu in deep sleep will wake-up from external source on receiving a pulse from high to low on the RST pin.
An ADXL345 accelerometer raises an interrupt HIGH on sensing motion and remains high until (I2C) READ to prevent multiple devices from interfering with each other
The following post was instrumental in my finding a solution
https://electronics.stackexchange.com/questions/158015/how-to-turn-continuous-signal-into-a-short-pulse-using-logic-gates

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Calculate the Li-Po Battery Level in ESP-Wroom-02
I am very new to micro controller and circuits. I am not at all with this field. But trying to create a home project where I have a device image attached below.

This is 18650 Lipo battery powered device. Here I want to calculate the battery level. After doing some research on google I found that I need to have Voltage Divider which I think I already included in this with 220k ohms and 100k ohms

People are using different ways to calculate it. Which I found in few examples. Which I am not able to understand at all, that what formula or values they are referring to calculate it.
if someone can help to understand that will be helpful. Here is how I am coding it which I saw somewhere on internet itself.
      #include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
//#include "DHTesp.h"

#define DHT_PIN       16

//SSID and Password of your WiFi router
const char* ssid = "Asus";
const char* password = "Xmv02488!!**";

ESP8266WebServer server(80); //Server on port 80

/***************************************************************
 * SETUP
 **************************************************************/
void setup(void){
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);     //Connect to your WiFi router
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  //If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP

  server.on("/", handleRoot);      //Which routine to handle at root location

  server.begin();                  //Start server
  Serial.println("HTTP server started");

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(A0, INPUT);

}
/***************************************************************
 * LOOP
 **************************************************************/
void loop(void){
  server.handleClient();          //Handle client requests

}

/***************************************************************
 * This function converts IPAddress struct to a String
 **************************************************************/
String IpAddress2String(const IPAddress& ipAddress)
{
  return String(ipAddress[0]) + String(".") +\
  String(ipAddress[1]) + String(".") +\
  String(ipAddress[2]) + String(".") +\
  String(ipAddress[3])  ;
}

/***************************************************************
 * This rutine is exicuted when you open its IP in browser
 **************************************************************/
 void handleRoot() {
  IPAddress ip_address = WiFi.localIP();
  String ip_str = IpAddress2String(ip_address);

  int nVoltageRaw = analogRead(A0);
  float fVoltage = (float)nVoltageRaw * 0.00486;

  float fVoltageMatrix[22][2] = {
    {4.2,  100},
    {4.15, 95},
    {4.11, 90},
    {4.08, 85},
    {4.02, 80},
    {3.98, 75},
    {3.95, 70},
    {3.91, 65},
    {3.87, 60},
    {3.85, 55},
    {3.84, 50},
    {3.82, 45},
    {3.80, 40},
    {3.79, 35},
    {3.77, 30},
    {3.75, 25},
    {3.73, 20},
    {3.71, 15},
    {3.69, 10},
    {3.61, 5},
    {3.27, 0},
    {0, 0}
  };

  int i, perc;

  perc = 100;

  for(i=20; i>=0; i--) {
    if(fVoltageMatrix[i][0] >= fVoltage) {
      perc = fVoltageMatrix[i + 1][1];
      break;
    }
  }

  server.send(200, "text/plain", "Hello from esp8266!\n\rIP: " + ip_str +
    ".\n\rTemp: " + "NO" +
    ", Hum: " + "NO" +
    "\n\r" + "NO" +
    "\n\r" + "Voltage: " + fVoltage +
    "\n\r" + "Charge: " + perc + '%');
}

This is a copied code. Where I am not sure about where they got the this formula and how they got the value of 0.00486
I copied this code from different source references. But I hope this will help you to understand the issue.
Any suggestions will be helpful!
Thank you! (In advance)

The biggest problem with the internet is the number of people that think they know what they are doing, but in reality have no idea, but still feel the need to post tutorials about that which they know nothing of .. chances are 0.00486 was either the result of "trial and error", or a case of "chinese whispers" .. code copied and copied and copied again, and somewhere along the line, there was a typo, or two, or three ... and you end up with purple monkey dishwasher (Simpsons reference)

The problem with LiPo batteries is that the discharge curve is very flat.  Here's an example:

As you can see, for about 95% of the life of the battery there is very little change in voltage.  You can't just take the voltage between "full" and "empty" and get a percentage from that. Instead you have to map points along that curve to different percentages.
The simplest way is to just have a set of percentages that you are interested in - every 5% as in the code you have above. Then you say "If the voltage is above this value then it's 100%. If it's above this next value down it's 95%. If it's above the next value down then it's 90%". etc.
The array fVoltageMatrix contains that mapping.  For 100% the voltage must be 4.2V or greater.  For 95% it must be 4.15V or greater. And so on.
If we take those voltage values from the array and plot them on a graph they look like this:

As you see that looks kind of similar. Quite flat, with a sudden drop off.
The code that gets the percentage charge simply reads the value from the ADC and converts it to a voltage by multiplying it by 0.004861, then it steps through the array one element at a time. The first time it finds one that fails the test "This percentage's threshold is less than the voltage" makes it take the previous one in the list as the percentage.  Personally, I think that's backwards and a bad way of doing it.  Instead, it should be the first one that passes the test "The voltage is greater than or equal to this percentage's threshold" that should be taken.  I'd rewrite the loop like this:
perc = 0;

for(i=0; fVoltageMatrix[i][0] > 0; i++) {
  if(fVoltage >= fVoltageMatrix[i][0]) {
    perc = fVoltageMatrix[i][1];
    break;
  }
}

1 The number 0.00486 is the number of volts applied to the input to give a 1 from the ADC. Incidentally, if I am using the right figures, I calculate it should be 0.003125.  1 * (1/1024) gives 0.000976563 (that's 1 volt maximum range on the ADC, multiplied by one bit - a 1024th since it's 10 bit resolution on the ESP8266). Multiply that by the ratio of the resistors ((R1 + R2)/R2) which is 3.2, and that gives 0.003125. To compress it, you get:  x = (R1 + R2) / R2 * 1/1024 = 320000 / 100000 * 0.000976563 = 0.003125
However, my numbers could be wrong...

Thank you so much for such a detailed explanation. It helped to understand a lot. Here if I use this float fVoltage = (float)nVoltageRaw * 0.0041015625; and I get a voltage reading of 4.2 which is awesome. I added a 100k ohms resister to the A0 to positive of my battery. Which makes a lot of sense now! :)

Another problem you can run into is that a lot of the A/D converters use the VCC as a voltage reference. Which means that as your input voltage drops (what you are trying to measure) the reference voltage also drops which means the values you are recording will not appear to change or at least will not give an accurate reference.

Below you can find the digital density meter I made for beer and the software I created for temperature and battery tracking.
1 . This part is the process I did to equalize the voltage coming to the voltage divider to the voltage of the battery.
float fVoltage = (float)nVoltageRaw * 1.23;)
You can calculate and find this value (1.23) according to your voltage divider.
But for some reason the battery status fluctuates a bit
2 . I used 2 BC238 transistors for the sensors and the voltage divider so that the ESP does not consume energy when not reading.voltage only passes when transistors are triggered
3 . float pot = map(a.acceleration.x, yogunlukreset0, yogunlukreset1, 997, 1100 );
This part was used to calibrate the device.

    #include <ESP32Firebase.h>

    #include "I2Cdev.h"
    //#include "MPU6050.h"
    #include <Adafruit_MPU6050.h>
    #include <Adafruit_Sensor.h>

    #include <Wire.h>
    #include "Adafruit_MCP9808.h"

    #define _SSID ""
    #define _PASSWORD ""
    #define REFERENCE_URL ""

     Firebase firebase(REFERENCE_URL);

     Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();
     Adafruit_MPU6050 mpu;
     sensors_event_t a, g, temp;

    #define uS_TO_S_FACTOR 1000000ULL  /* Conversion factor for micro seconds to seconds */
    #define TIME_TO_SLEEP  3600       /* Time ESP32 will go to sleep (in seconds) */

    #define bc1 33
    #define bc2 16

     RTC_DATA_ATTR int bootCount = 0;
     const int potPin = 34;

     #include <Preferences.h>
     Preferences pref;

    namespace{
     float yogunlukreset0;
     float yogunlukreset1;

    }
    void wakeup_reason(){
      esp_sleep_wakeup_cause_t wakeup_reason;
      wakeup_reason = esp_sleep_get_wakeup_cause();

    }

    void setup() {

      Serial.begin(115200);
      delay(100);
      pinMode(bc1, OUTPUT);
      pinMode(bc2, OUTPUT);
      delay(100);
      digitalWrite(bc1, HIGH);
      digitalWrite(bc2, HIGH);
      delay(100);

      Wire.begin();
      WiFi.mode(WIFI_STA);
      WiFi.disconnect();
      delay(1000);
      Serial.println();
      Serial.println();
      Serial.print("Connecting to: ");
      Serial.println(_SSID);
      WiFi.begin(_SSID, _PASSWORD);

      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print("-");
      }

      Serial.println("");
      Serial.println("WiFi Connected");

      Serial.print("IP Address: ");
      Serial.print("http://");
      Serial.print(WiFi.localIP());
      Serial.println("/");

      if (!tempsensor.begin(0x18)) {
      Serial.println("Couldn't find MCP9808! Check your connections and verify the address is correct.");
      while (1);
      }
      if (!mpu.begin()) {
        Serial.println("Failed to find MPU6050 chip");
        while (1) {
          delay(10);
        }
     }

    ++bootCount;

      Serial.flush();
      pref.begin("Relay-State", false);
      yogunlukreset0 = pref.getFloat("namespace", false);
      yogunlukreset1 = pref.getFloat("namespa", false);

    }

    void loop() {

      mpu.setCycleRate(MPU6050_CYCLE_20_HZ);

      mpu.getEvent(&a, &g, &temp);

      tempsensor.wake();

      pref.putFloat("namespace", yogunlukreset0);
      pref.putFloat("namespa", yogunlukreset1);

      float c = tempsensor.readTempC();

      String reset2 = firebase.getString("Data/RT2");

      if (reset2 == "1"){
      String reset0 = firebase.getString("Data/RT0");
      String reset1 = firebase.getString("Data/RT1");
      String reset3 = firebase.getString("Data/RT3");

      if (reset0=="1") {
        yogunlukreset0 = (a.acceleration.x);
        }
      if (reset1=="1") {
        yogunlukreset1 = (a.acceleration.x);
        }

      if (reset3 == "1"){
        pref.clear();
        bootCount = 0;
        }

      }

      if (reset2 == "0"){

      float pot = map(a.acceleration.x, yogunlukreset0, yogunlukreset1, 997, 1100 );

      int nVoltageRaw = analogRead(potPin);

      float fVoltage = (float)nVoltageRaw * 1.23;

      float fVoltageMatrix[22][2] = {
        {4150, 100},
        {4130, 95},
        {4110, 90},
        {4080, 85},
        {4040, 80},
        {4010, 75},
        {3970, 70},
        {3930, 65},
        {3890, 60},
        {3850, 55},
        {3810, 50},
        {3760, 45},
        {3710, 40},
        {3660, 35},
        {3610, 30},
        {3550, 25},
        {3490, 20},
        {3430, 15},
        {3370, 10},
        {3320, 5},
        {3270, 0},
        {0, 0}
      };

      int i, perc;

      perc = 100;

      for(i=20; i>=0; i--) {
        if(fVoltageMatrix[i][0] >= fVoltage) {
          perc = fVoltageMatrix[i + 1][1];
          break;
        }
      }

      firebase.setFloat("Data/YG", pot);
      firebase.setFloat("Data/TM", c);
      firebase.setFloat("Data/SYC", bootCount);
      firebase.setFloat("Data/VOLT", fVoltage);
      firebase.setFloat("Data/ORAN", perc);

      digitalWrite(bc1, LOW);
      digitalWrite(bc2, LOW);

      wakeup_reason();
      esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
      esp_deep_sleep_start();
      delay(50);
      }

    }

One problem I have with the ESP8266 is the crappy results from the A/D converter. There are a number of hoops that you need to go through for the planets to align in order to get consistent readings. See  Fluctuating ADC with stabilized source https://github.com/esp8266/Arduino/issues/2070
The other issue I have is with the assumption that the range of operation of the A/D is 0-1.0 volts and that certainly is not the case.

I calculate it should be 0.003125. 1 * (1/1024) gives 0.000976563
  (that's 1 volt maximum range on the ADC

The above shows how precise our calculations can be but unfortunately the six digits of precision gets thrown out the window if the assumed 1 volt top end has variations of 5%. Unfortunately there are no specifications given as far as the A/D converter in the miniscule spec sheet.
Yes the ESP8266 A/D can be calibrated, and measurements taken under controlled conditions. But make sure that you do the required work and verify the results under all operating conditions before you trust your results.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Problem with SPI comms using NodeMCU v 3, Nano and SD
Recently I bought a NodeMCU 8266 v 3 (Lolin) and it works fine. I set up a Catalex SD card module (with a built-in 5-3.3V regulator) and all was good. Then I set the Lolin with an Arduino Uno and or a Nano working for SPI communications and all worked properly. So when I tried to put the Lolin as master, and two slaves (a Nano and an SD Card), all working with SPI, it did not work.
If I set up the SD card Vcc to 5 volts, the Lolin can "see" it and initializes it, but the communication between the Lolin and the Nano crashes (the Lolin can send the data but receives only trash; the Nano can receive and consequentely responds). When I disconnect the SD Vcc cable the communications works.
So I tried to remedy this situation using a bidirectional level shifter and the Lolin seems frozen.
Any help is welcome.

Code of Lolin (as Master).
/*Master - ESP12e create a variable string to be sent to slave - Nano_ChipSelect
    and receive a variable answer.

    Master ESP12e use:    COM5
          * SPI communications with a NANO as slave in GPIO 0 = D3
          * WiFi communication
          * a DS3231 for RTC
          * a catalex SD memory
*/

/*---------------( Import needed libraries )-------------------------------------*/
#include <ESP8266WiFi.h>                            // WiFi
#include <WiFiClientSecure.h>                       // SSL Client
#include <SPI.h>                                    // SPI comms
#include <SD.h>                                     // SD mem card
#include <Wire.h>                                   // RTC comms
#include "RtcDS3231.h"                              // RTC by maluma

/*---------------( Define Constants )--------------------------------------------*/
#define Nano_ChipSelect             D3              // Slave select signal for NANO
#define SD_ChipSelect               D8              // Slave select signal for SD

/*---------------( Declare objects )---------------------------------------------*/
RtcDS3231<TwoWire>    Rtc(Wire);
File                  myFile;
WiFiClientSecure      client;

/*---------------( Declare Special settings--------------------------------------*/
SPISettings           Set_SPI_NANO( 1000000, MSBFIRST, SPI_MODE0 );

/*---------------( Declare Constants )--------------------*/
String        defaultChatId         = "5";
char          ssid[]                = "scouts";     // network SSID (name)
char          password[]            = "R";   // network key

/*---------------( Declare Variables )-------------------------------------------*/
bool          switch_Red            = false;
bool          switch_Yell           = false;
bool          switch_Green          = false;
unsigned int  temp_ESP12e            = 0;
unsigned int  temp_nano             = 0;
unsigned int  hum_nano              = 0;
char          datestring[20];
char          Nano_S_to_send[]      = "0000000000000000000000000|";
//                                    "RRYYGcGYYYYcMMDDHcHMMSScc|"
//                                     01234567890123456789012345
//                                     0         1         2
char          Nano_S_to_receive []  = "0000000000000000000000000|";
//                                    "TTTTTcHHHHHcIIIIIcDDDDDcc|
//                                     01234567890123456789012345
//                                     0         1         2
byte          Leds                  = 0;

#define countof( a ) ( sizeof( a ) / sizeof( a[ 0 ] ) )

void _printDateTime( const RtcDateTime& dt ) {  //---------------------------------
    snprintf_P(datestring,
            countof(datestring),
            PSTR("%04u/%02u/%02u %02u:%02u:%02u"),
            dt.Year(),
            dt.Month(),
            dt.Day(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );
}

void _create_data_for_nano() {  //-------------------------------------------------
  RtcDateTime now = Rtc.GetDateTime();
  _printDateTime( now );
  //;
  //             RRYYGcGYYYYcMMDDHcHMMSScc|
  //             0000000000000000000000000|
  Nano_S_to_send[ 0 ] = _getbit( Leds, 0 );  // red status
  Nano_S_to_send[ 1 ] = _getbit( Leds, 1 );  // red status
  Nano_S_to_send[ 2 ] = _getbit( Leds, 2 );  // yellow status
  Nano_S_to_send[ 3 ] = _getbit( Leds, 3 );  // yellow status
  Nano_S_to_send[ 4 ] = _getbit( Leds, 4 );  // green status
  Nano_S_to_send[ 5 ] = _Nano_CRC( 0, 5 );
  Nano_S_to_send[ 6 ] = _getbit( Leds, 5 );  //green status
  Nano_S_to_send[ 7 ] = datestring[ 0 ];  //y
  Nano_S_to_send[ 8 ] = datestring[ 1 ];  //y
  Nano_S_to_send[ 9 ] = datestring[ 2 ];  //y
  Nano_S_to_send[ 10 ] = datestring[ 3 ];  //y
  Nano_S_to_send[ 11 ] = _Nano_CRC( 6, 5 );
  Nano_S_to_send[ 12 ] = datestring[ 5 ];  //m
  Nano_S_to_send[ 13 ] = datestring[ 6 ];  //m
  Nano_S_to_send[ 14 ] = datestring[ 8 ];  //d
  Nano_S_to_send[ 15 ] = datestring[ 9 ];  //d
  Nano_S_to_send[ 16 ] = datestring[ 11 ];  //h
  Nano_S_to_send[ 17 ] = _Nano_CRC( 12, 5 );
  Nano_S_to_send[ 18 ] = datestring[ 12 ];  //h
  Nano_S_to_send[ 19 ] = datestring[ 14 ];  //m
  Nano_S_to_send[ 20 ] = datestring[ 15 ];  //m
  Nano_S_to_send[ 21 ] = datestring[ 17 ];  //s
  Nano_S_to_send[ 22 ] = datestring[ 18 ];  //s
  Nano_S_to_send[ 23 ] = _Nano_CRC( 18, 5 );
  Nano_S_to_send[ 24 ] = _Nano_CRC( 0, 24 );
}

char _getbit( byte data, byte pos ){
  byte b = data >> pos;
  b = b & 1;
  char b1[] = { '0' };
  if( b ) b1[ 0 ] = '1';
  return b1[ 0 ];
}

char _Nano_CRC( byte pos, byte lon ) {  //---------------------------------------------
  int  suma = 0;
  bool par  = false;
  for( int i = 0 ; i < lon ; i++ ) {
    suma += char( Nano_S_to_send[ i + pos ] );
    if( par )  {
      suma += 2 * char( Nano_S_to_send[ i + pos ] );
    }
    par = !par;
  }
  int  b = suma/10;
  if( suma != b*10 )  b++;
  b *= 10;
  char resultado[ 2 ];
  itoa( b - suma, resultado, 10 );
  return resultado[ 0 ];
}

void _transfer_data_to_NANO_by_spi() {  //----------------------------------------
  char c[2];
  digitalWrite( SD_ChipSelect, HIGH );
  cli();
  byte index2 = 0;
  SPI.beginTransaction( Set_SPI_NANO );
  digitalWrite( Nano_ChipSelect, LOW );
  byte num_char_to_transfer = sizeof( Nano_S_to_send ) ;
  for( byte index = 0 ; index <= num_char_to_transfer ; index++ ) {
    c[ 1 ] = ( Nano_S_to_send[ index ] );
    c[ 0 ] = SPI.transfer( c[ 1 ] );
    if( index != num_char_to_transfer ) Nano_S_to_receive [ index2 ] = 'E';
    if( c[ 0 ] != '\0' ) {
      Nano_S_to_receive [ index2 ] = c[ 0 ];
    }
    if( index != 0 ) index2++;
    delayMicroseconds( 2 );
  }
  digitalWrite(Nano_ChipSelect, HIGH);
  //Serial.print("-->");Serial.print(Nano_S_to_receive);Serial.println("<--");
  sei();
  SPI.endTransaction ();
}

String _txt2str( int valor ){  //-------------------------------------------------
  char v_txt[]= "000";
  itoa( valor, v_txt, 10 );
  String v_text = "";
  for( int i = 0 ; i < 4 ; i++ ){
    if( v_txt[ 3-i ] != '\0' ) {
      v_text = v_txt[ 3-i ]+ v_text;
    }
  }
  return v_text;
}

int _convierte( byte pos ){  //---------------------------------------------------
    char temporal [] = "     ";
    for( int i = 0 ; i < 4 ; i++ )  {
      temporal [ i ] = Nano_S_to_receive [ i + 1 + pos ];
    }
    int temp = atoi( temporal);
    return temp;
}

void setup() {   /*-----------( SETUP: RUNS ONCE )------------------------------*/
  pinMode( SD_ChipSelect,   OUTPUT );          // configure the line as output
  pinMode( Nano_ChipSelect, OUTPUT );          // configure the line as output

  Serial.begin( 115200 );              // start the serial monitor
  digitalWrite( SD_ChipSelect,   HIGH );       // turn to HIGH to disable
  digitalWrite( Nano_ChipSelect, HIGH );       // turn to HIGH to disable slave

  Serial.println();
  Serial.print( "compiled: " );Serial.print( __DATE__ );
  Serial.print( " at " );Serial.println( __TIME__ );
  Serial.print( "Connecting Wifi: " );
  Serial.println( ssid );

  Rtc.Begin();

  RtcDateTime compiled = RtcDateTime( __DATE__, __TIME__ );
  RtcDateTime now = Rtc.GetDateTime();
  _printDateTime( now );
  Serial.print(" --- Initialized WiFi at ");
  Serial.println( datestring );

  if ( !Rtc.IsDateTimeValid() )   {
        Serial.println( "RTC lost confidence in the DateTime!" );
        Rtc.SetDateTime( compiled );
        RtcDateTime now = Rtc.GetDateTime();
        _printDateTime( now );
  }

  if( !Rtc.GetIsRunning() )  {
    Serial.println( "RTC was not actively running, starting now" );
    Rtc.SetIsRunning( true );
  }

   if ( now < compiled )     {
    Serial.println( "RTC is older than compile time!  (Updating DateTime)");
    Rtc.SetDateTime( compiled );
  } else if( now > compiled )    {
      Serial.println( "RTC is newer than compile time. (this is expected)" );
    } else if ( now == compiled )     {
        Serial.println( "RTC is the same as compile time!");
      }
  Rtc.Enable32kHzPin( false );
  Rtc.SetSquareWavePin( DS3231SquareWavePin_ModeNone );

  Serial.print( "Initializing SD card..." );

  SPI.begin();
  /* begin SPI at 1 Mbit rate most significat bit first & mode 0 */
  SPI.beginTransaction( SPISettings( 1000000, MSBFIRST, SPI_MODE0 ) );
  digitalWrite( SD_ChipSelect, LOW );

  if ( !SD.begin( SD_ChipSelect ) ) {
    Serial.println( "initialization failed!" );
    return;
  }
  myFile = SD.open( "Log_1.txt", FILE_WRITE );
  if (myFile) {                           // if the file opened okay, write to it:
    myFile.println( "YYYY:MM:DD:HH:MM:SS:TNANO:HNANO:TESP12e" );
    // close the file:
    myFile.close();
  } else {                             // if the file didn't open, print an error:
    Serial.println( "error opening file Log_1.txt" );
  }

  digitalWrite( SD_ChipSelect, HIGH );
  SPI.endTransaction();

  Serial.println( "*****  initialization done. ******" );
}

void loop() {  //-----------------------------------------------------------------

  Serial.println("*********** E S P 1 2 ***********");
  RtcTemperature temp = Rtc.GetTemperature();
  temp_ESP12e = temp.AsFloat() * 100;                         // System Temperature

  _create_data_for_nano();
  _transfer_data_to_NANO_by_spi();       // transfer routine to send and receive data
  //_check_received_data();

  Serial.print( "->NANO:" );Serial.print(    Nano_S_to_send );Serial.println(":");
  Serial.print( "NANO<-:" );Serial.print( Nano_S_to_receive );Serial.println(":");

  Leds++;
  if( Leds > 64 ) Leds = 0;
  delay(5000);
}

Code of nano ( as slave )
/* Slave - Nano receive a variable string, byte by byte from
 *  master - ESP12e and create a variable answer

      Slave NANO use:    COM3
           * SPI communications
           * an AM2302 sensor for temperature and humidity
           * timers
*/

/*---------------( Import needed libraries )-------------------------------------*/
#include <SPI.h>
#include <DHT.h>
#include "DHT_U.h"
#include "SimpleTimer.h"
#include "Adafruit_Sensor.h"

/*---------------( Define Constants )--------------------------------------------*/
#define switch_Yell       2
#define switch_Green      4
#define switch_Red        6
#define DHTPIN            9         // Pin connected to the DHT sensor.

#define DHTTYPE           DHT22     // DHT 22 (AM2302)

/*---------------( Declare objects )---------------------------------------------*/
SimpleTimer timer;
DHT_Unified dht(DHTPIN, DHTTYPE);

/*---------------( Declare Special settings--------------------------------------*/

/*---------------( Declare Constants )--------------------*/

/*---------------( Declare Variables )-------------------------------------------*/
uint32_t       waiting_for_AM2302;
char           string_to_receive[] = "0000000000000000000000000|";
//                                   "RRYYGcGYYYYcMMDDHcHMMSScc|"
//                                    01234567890123456789012345
//                                    0         1         2
char           string_to_answer[]  = "0000000000000000000000000|";
//                                   "TTTTTcHHHHHcIIIIIcDDDDDcc|
//                                    01234567890123456789012345
//                                    0         1         2
volatile byte  index;
volatile bool  receivedone;  /* used as reception complete flag */
byte           Dummy               = 0;

// function to be called repeatedly by timer function
void Read_AM2302() {  //-----------------------------------------------------------

  int tempera    = -1;
  int humidit    = -1;
  int illumin    = -1;
  int dummy       = -1;
  sensors_event_t event;
  // Get temperature event and print its value.
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println("Error reading temperature!");
  }
  else {
    tempera = event.temperature * 10;
  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println("Error reading humidity!");
  }
  else {
    humidit = event.relative_humidity * 10;
  }

//  tempera = 9;
//  humidit = 72;
  illumin = 143;

  _create_answer( tempera,   0 );
  string_to_answer[  5 ] = _CRC(  0,  5 );
  _create_answer( humidit,      6 );
  string_to_answer[ 11 ] = _CRC(  6,  5 );
  _create_answer( illumin, 12 );
  string_to_answer[ 17 ] = _CRC( 12,  5 );
  //_create_answer( Dummy,       18 );
  string_to_answer[ 18 ] = _getbit( Dummy, 4 );
  string_to_answer[ 19 ] = _getbit( Dummy, 3 );
  string_to_answer[ 20 ] = _getbit( Dummy, 2 );
  string_to_answer[ 21 ] = _getbit( Dummy, 1 );
  string_to_answer[ 22 ] = _getbit( Dummy, 0 );
  string_to_answer[ 23 ] = _CRC( 18,  5 );
  string_to_answer[ 24 ] = _CRC(  0, 24 );
  /*
  Serial.print(" Temperature =");Serial.println( tempera );
  Serial.print(" Humidity     =");Serial.println( humidit );
  Serial.print(" Illumination =");Serial.println( illumin );
  Serial.print(" Dummy       =");Serial.println( Dummy   );
  Serial.print("Answer-->"); Serial.println( string_to_answer );
  */
}

char _getbit( byte data, byte pos ){
  byte b = data >> pos;
  b = b & 1;
  char b1[] = { '0' };
  if( b ) b1[ 0 ] = '1';
  return b1[ 0 ];
}

char _CRC( byte pos, byte lon ) {  //----------------------------------------------
  int  suma = 0;
  bool par  = false;
  for( int i = 0 ; i < lon ; i++ ) {
    suma += char( string_to_answer[ i + pos ] );
    if( par )  {
      suma += 2 * char( string_to_answer[ i + pos ] );
    }
    /*
    Serial.print(" i=");Serial.print(i);
    Serial.print(" d=");Serial.print(string_to_answer[ i + pos ] );
    Serial.print(" s=");Serial.println( suma);
    */
    par = !par;
  }
  int  b = suma/10;
  if( suma != b*10 ) b++;
  b *= 10;
  char result[ 2 ];
  itoa( b - suma, result, 10 );
  /*
  Serial.print( "-S-" );Serial.print( sum );      Serial.println("---");
  Serial.print( "-B-" );Serial.print( b );        Serial.println("---");
  Serial.print( "-R-" );Serial.print( result[ 0 ] );Serial.println("---");
  */
  return result[ 0 ];
}
                   //      9         0
void _create_answer( int data, byte pos) {  //-------------------------------------
  char temporal[] = {'\0','\0','\0','\0','\0'};  // masc
  byte longitud = 5;          // posicion desde 0 hasta n
  byte puntero = pos + longitud; //5
  itoa( data, temporal, 10 );//9
  //Serial.print("-t-");Serial.println( temporal );
  //Serial.print("-s-");Serial.println( sizeof temporal );
  for( int i = longitud ; i >= 0 ; i-- ) {
    //Serial.print("-val-");Serial.println( (temporal[i]) );
    if( temporal[i] != '\0' ) {
    string_to_answer[ puntero-- ] = temporal [ i ];
    }
  }
}

// SPI interrupt routine
ISR (SPI_STC_vect) {  //-----------------------------------------------------------
  uint8_t oldsrg = SREG;
  cli();
  string_to_receive[ index ] = SPDR;
  SPDR = string_to_answer[ index ];
  if( string_to_receive [index] == '\0' ) receivedone = true;
  if( index < sizeof( string_to_receive ) ) index++;
  sei();
  SREG = oldsrg;
}

void setup (){  //-----------------------------------------------------------------
  Serial.begin (115200);

  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);    // turn on SPI in slave mode
  SPCR |= _BV(SPIE);   // turn on interrupts

  index = 0;
  receivedone = false;
  SPI.attachInterrupt();    /* Attach SPI interrupt */
  dht.begin();
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  dht.humidity().getSensor(&sensor);
  waiting_for_AM2302 = sensor.min_delay / 1000;
  Serial.println("------------------------------------");
  Serial.println("Temperature");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value);
  Serial.println(" *C");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value);
  Serial.println(" *C");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution);
  Serial.println(" *C");
  Serial.println("------------------------------------");
  Serial.println("Humidity");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value);
  Serial.println("%");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value);
  Serial.println("%");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution);
  Serial.println("%");
  Serial.println("------------------------------------");
  timer.setInterval( waiting_for_AM2302, Read_AM2302 );
  pinMode( switch_Red,   OUTPUT );
  pinMode( switch_Yell,  OUTPUT );
  pinMode( switch_Green, OUTPUT );
  digitalWrite( switch_Red,   LOW );
  digitalWrite( switch_Yell,  LOW );
  digitalWrite( switch_Green, LOW );

}

void loop () {  //-----------------------------------------------------------------
    timer.run();
  if (receivedone) {         /* Check and print received buffer if any */
    Serial.println( "************ N A N O ************" );
    Serial.print( "ESP12e<-:" );Serial.print( string_to_receive );Serial.println( ":" );
    Serial.print( "->ESP12e:" );Serial.print( string_to_answer );Serial.println( ":" );
    //_check_received_data();
    digitalWrite( switch_Red,   string_to_receive[ 1 ] - 48 );
    digitalWrite( switch_Yell,  string_to_receive[ 3 ] - 48 );
    digitalWrite( switch_Green, string_to_receive[ 6 ] - 48 );
    string_to_receive[index] = 0;
    index = 0;
    receivedone = false;

    Dummy++;
    if( Dummy > 32 ) Dummy = 0;
  }
}

here is the Serial monitor view
Master
    ******* L O L I N *******
    ->NANO:1111191201800204282452676|:
    NANO<-:000EEEEEEEE :                     --- connected at 5V
    ******* L O L I N *******
    ->NANO:0000080201810204282453192|:
    NANO<-:00<:
    ******* L O L I N *******
    ->NANO:0000080201810204282453642|:
    NANO<-:EEEEEEEEEEEEEEEEEEEEEE:          ---- connected at 3.3 V
    ******* L O L I N *******
    ->NANO:1000070201810204282454160|:
    NANO<-:0000990007250014320806510|:      ---- disconnected

Slave
    ************ N A N O ************
    LOLIN<-:1111191201800204282452676|
    ->LOLIN:0000990007250014320806510|
    ************ N A N O ************
    LOLIN<-:0000080201810204282453192|
    ->LOLIN:0000990007250014320806510|
    ************ N A N O ************
    LOLIN<-:0000080201810204282453642|
    ->LOLIN:0000990007250014320806510|
    ************ N A N O ************
    LOLIN<-:1000070201810204282454160|
    ->LOLIN:0000990007250014320806510|

how did you connect the Slave Select (SS, CS) pins

how are you getting 5v on the lolin board? (not from VIN).

Hi, I am getting the 5v from +5V pin of Nano or VV of Lolin, or as you can see in the picture both MCUs are together for test but when this work I´m going to put a power supply connected to Vin at both MCUs, and Vcc of the DS3231 and Catalex Sd card module.

For Nano I´m using D3 of Lolin, and for the SD I´m using D8 (Yellow wires). D1&D2 are for I2C comms with the RTC.

is the ground of lolin connected with ground of Nano?

Yes, in the picture the groud cable between Esp8266 and Nano is not showed, but I try at both forms and they are connected to the same PC by shielded USB cables

the USB didn't do a good ground connection in my SPI setup of Nano with Wemos

Use a tri-state buffer on the MISO pins of the SPI devices using the slave select as enable. It's the only way I could make it work.

Thank you, I was thinking the same, it is a hardware problem; I am waiting for a TI SN74LS07 ex buffer with and average propagation
delay time of 12 ns according its datasheet.

Hi jurag, dandavis and @sundayfantasy, updating my issue. The SD card has build-in an TI sn74lvc125a Quadruple Bus Buffer Gate With 3-State Outputs but for an unknow reason it never stop the MISO signal, so I just put a fairchild 4N35 and belive or not it is working fine. I´m waiting for a new SD and additional hardware to check what is happend here.

HI @sundaysfantasy, I just put a 4N35 and it is working

Good to know it works with an optocoupler too.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Looking for a waterproof SPI temperature sensor
In my current project I'm using a DS18B20, which seems to be the only temperature sensor to show up when googling for waterproof temperature sensor for an arduino.
The sensor itself is fine, however, I'm outputting the sensor's data to a SPI screen, and whenever the sensor is called to read data I believe the SPI communication is interrupted because of 1-Wire, and you can see a white flicker on the screen. The background LED is flashing more brightly for one frame. It's almost unnoticeable, but it bothers me.
I'm not using delays, and I'm not redrawing unnecessary elements on the screen again. Only dynamic elements are refreshed when they need to, static elements are only drawn once on the screen. The sensor is called every 5 seconds with a comparison:
if(currentTime - lastTimeQueried >= delay){
    lastTimeQueried = currentTime;
    temperature = new temperature;
    return temperature;
} else {
    return temperature;
}

I also tried a function where I'm constantly calling the sensor and only drawing on the screen if there's a change in temperature, but then the screen is flickering all the time. Thus I conclude that the flickering is caused by the actual calling of the sensor, and not from redrawing anything on the screen.
So I'm wondering if there's an alternative to the DS18B20 that communicates via SPI, and that I can use in an aquarium, so I don't have to use both protocols in my project.
Edit:
As requested some more of my code and wiring:
The screen is wired to the ICSP headers on my Arduino Mega 2560 and power is supplied via 5V on a powersupply that is connected to my breadboard.
The DS18B20 is wired to pin 29 on the Arduino and is also supplied with power via 5V on the same powersupply.
//TFT SPI
#define TFT_DC 9
#define TFT_CS 10
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

//SD Card Reader SPI
//#define SD_CS 4

//Touchscreen I2C
UTouch  myTouch(5, 8, 6, 7, 2);  //(T_CLK, T_CS, T_DIN, T_DOUT, T_IRQ)

#define ONE_WIRE_BUS 29
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

Here are some more variables that I have defined to help with using the sensor:
//Temperature measurement
unsigned long lastTempMeasure;  //Holds last unix timestamp temperature was measured at
char tempMeasureDelay = 5;      //Call temperature every 5 seconds
float sensorTemp;               //Holds measured temperature

In my loop I then use this function:
tft.print(temperatureCall());

and then:
float temperatureCall(){
  //get unix time for right now
  unsigned long currentUnix = now();

  //if 5 seconds passed since last poll, ask for new temperature, else return old measurement
  if(currentUnix - lastTempMeasure >= tempMeasureDelay){
    lastTempMeasure = currentUnix; //save last polling time

    sensors.requestTemperatures();
    sensorTemp = sensors.getTempCByIndex(0);

    return sensorTemp;
  } else {
    return sensorTemp;
  }
}

As I said, the flicker only occurs when these two are used every 5 seconds:
sensors.requestTemperatures();
sensorTemp = sensors.getTempCByIndex(0);

Edit 2:
Pic of wiring:

Can you share your wiring including LCD display over SPI and DS18B20 and some more of your code?

@Sener I have updated my post

It sounds more like a power issue rather than a communication issue. How are you powering the backlight for the display?

Thanks for the details, seeing big picture helps most of the time.
I consider, SPI pins are not shared with some other SPI device.
So, the sensor is on one of the digital pins which is also fine. But, since the onewire is using bit-banging, trying some other pins for the sensor would be wise.
Besides this, the backlight led is not obvious. I think it is directly connected to 5V, isn't it? I recommend measuring voltage and the current board draws. If they fluctuates (voltages drops) or making a sudden move than we can take it from there.

What I have also thought of that it might indeed be a powering issue since the sensor is using a pullup resistor on the data line which is connected to 5V.
@Majenko the backlight LED is powered by the powersupply via 5V.
I will update my post with a picture of the wiring

@Sener why would it be wise to try a different pin for the sensor? What other pin would you recommend?

It really looks like sudden voltage drop or lack of current (tiny) when the sensor is active.for reading. But, datasheet says it is not dramatic, 1mA to 4mA.
But, apart from this, what I say that, I have those LCD's running on one of my products are not rock solid. In a batch, some of their backlight are bright some faded, some flickering.

Trying different pin is always a case I follow when debugging some issues in order to eliminate inconsistent design on some gates particularly clone components. You never know.

Hm, definitely food for thought. Will look more into this. Unfortunately I can't really measure any voltage drop with my multimeter which just shows mostly constant values on the backlight. Definitely no drops or peaks every 5 seconds.
This project might become a product, but at that stage I will be working together with a friend who is an electrician to help me with this, so he might know more.
Thanks for sharing your knowledge guys, this was really driving me a little nuts, knowing what's behind it or at least pushing me into the right direction definitely eased my mind.

Any time. A last note, you may try to place a 10uF Electrolytic on your power rail between GND and 5V. This can buffer (buy) some time when power is affected during sensor reading. Good luck with your project.

The 1-wire protocol uses specific timing. To do that, the OneWire library turns off the interrupts temporarily to create that signal. You can test that by turning off the interrupts for some time to see what will happen. Is there really no time for the OneWire library without disturbing the display? Perhaps the sketch needs to be fixed. There are good i2c temperature sensors. You can make them waterproof with food-safe materials. The best solution might be to replace the display and use a smart display with serial communication.

@Jot there is a clock on the display that also shows seconds. Maybe I can jerry-rig something in, but then it may slow down the entire sketch.

@Sener I have added a capacitor to my wiring. Another interesting observation I have made is that if I connect ground from my rail to the ground of my arduino, the screen turns completely white after the sketch ran for 5 seconds, presumably because it then calls the temperature of the sensor..
When I remove the capacitor, the same thing happens, but only after 10 or 15 seconds.

What you are saying reminds me my another experience with running two SPI's together. If you don't place resistors (4k7) serially connected to MOSI and SCK pins, they were effecting each others and my TFT 2.2'' display was going white. If so, what @jot says may be quite relevant to your issue.
You may be also try another version of 1-wire libraries.
Let's say 1-wire library

@Sener I already used 1k resistors on every data line. I tried 5k resistors, but then I couldn't keep the display running. It would display one frame and then do weird stuff. Tried with 2k resistors too which seems to have improved the issue a little. Unfortunately I don't have 4.7k resistors on hand...I should really expand from the parts that I have available from my tutorial kit.

There is a delay in the DallasTemperature requestTemperatures() function - it blocks until the temperature conversion is complete unless you have previously called setWaitForConversion(FALSE). If you did that, you would still have to wait for the conversion but you can do it an a non-blocking manner, and I don't see that happening in your code.

Thank you.
Is this something I need to call once in the setup? Or every time I am polling temperature from the sensor?

Looking at this DS18b20 library, the flag does not appear to get changed except by an external call, so setting it once should be sufficient. [Sorry for my typo in the original reply].


text:
What is the best vehicle platform to begin with (e.g. tracked, four-wheel drive)
Despite many articles on the topic of vehicle platforms, none of them seem to recommend the best one to start with. Later on I am sure I will seek an exact kind of chassis for autonomous vehicle construction, but now I am looking to learn the basics of this area of the Arduino world. If you could give me a simple recommendation for the general category of vehicle platform to use it would be much appreciated. I will be using an ultrasonic distance sensor coupled with a servo motor to detect obstacles, so it is a very simple project. Thank you so much.

SparkFun's Magician Chassis is a very simple, very flexible chassis for starting out. Also comes as part of the RedBot Kit.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Use pointer in calculation results in error
I'm building a project to measure/track flyball dog races.
The dogs timings are measured by photoelectric sensors at the start/finish line of the racing lane.
I have most of my code working (available on github) but I'm having some difficulties in handling very short crossings of dogs. Since I cannot realistically run a real race at home next to my development machine :-), I'm trying to build a simulator class which gives the triggers that would normally come from my photoelectric sensors.
I have a RaceHandler class which has the following in its header file:
class RaceHandlerClass
{
 public:
   long* lRaceStartTime = &_lRaceStartTime;

 private:
   long _lRaceStartTime;
}
extern RaceHandlerClass RaceHandler;

As you can see I made a public pointer lRaceStartTime which points to the private _lRaceStartTime member variable.
This might seem stupid/strange, but it really should a private member variable, I just want to 'temporarily' make it publicly available, so that I can use it in a temporary 'simulator' class to simulate a race towards my code.
Then I want to use this public pointer in the Simulator class like so:
long* lRaceStartTime = RaceHandler.lRaceStartTime;
long lRaceElapsedTime = micros() - lRaceStartTime;

However I get the following error when trying to compile this:

error: invalid operands of types 'long unsigned int' and 'long int*'
  to binary 'operator-'

I'm afraid my c++ knowledge ends here and I have no clue what I should do different to fix this...
Any help would be greatly appreciated!

Since I cannot realistically run a real race at home next to my development machine - how about mice?

Try this:
long* lRaceStartTime = RaceHandler.lRaceStartTime;
long lRaceElapsedTime = micros() - *lRaceStartTime;

You assigned the pointer to lRaceStartTime on the first line, but on the second line you are subtracting the pointer from micros() which returns an unsigned long.  You need to dereference the pointer before subtracting. Also you might consider making all your longs unsigned to match the return type of micros() http://arduino.cc/en/reference/micros

Thanks, this indeed solved my problem. Guess I need a little more practice with pointers...

No worries, happy to help.  Feel free to post more questions, this site needs to get out of beta!

I realise your question was but a simple query on syntax. But I would like to point out that the whole idea of object orientation is encapsulating functions and data so that external calls do not have to know about the internal-workings of that class.
It's common with object oriented programming to use 'getters' and 'setters' to modify private member-variables of the class. You really should not be giving a pointer to a private member. If you need to read/write it, add a setter function.
class RaceHandler
{
public:
    void setStartTime()
    {
        race_start_time = micros();
    }

    void setStartTime(unsigned long start_time)
    {
        race_start_time = start_time;
    }

    unsigned long getStartTime()
    {
        return race_start_time;
    }

    unsigned long getElapsedRaceTime()
    {
        return micros() - race_start_time;
        // TODO: handle overflow of micros() after ~72 minutes
        // maybe use millis() instead
    }

private:
    unsigned long race_start_time;
}

Obviously this is laborious.  Some languages have special support for getters and setters to provide the functionality with less syntax.
Time is always positive, use an unsigned long.  As people have already said, millis() & micros() return an unsigned long too.
RaceHandler race1;

race1.setStartTime();

[...]

unsigned long elapsed_time = race1.getElapsedRaceTime();

Time is always positive, use an unsigned long. - whilst this is quite true on the Arduino, I recently discovered that time_t is typedef'd to signed integer. In other words, you can represent times before 1st January 1970 by using negative numbers. Of course, this doesn't apply on the Arduino, as the concept of millis() returning time before the system was reset doesn't make a lot of sense.

@Nick Gammon - Yep, time_t is signed.  We've got until 2038 to sort that out ;)

Which is getting increasingly close. :)


text:
How to dynamically switch between between 2 objects?
I have a 40x4 LCD which internally consists of 2 40x2 LCDs.
To control this LCD I have to create 2 LiquidCrystal objects and than later on in code decide which one to use depending on which of the 4 lines I want to change.
Due to the size of my project, I split all the LCD handling off to a separate class.
To make my code as readable and easy as possible, I want to create a member method of this class, to which I can just pass line number 1-4, and have this method take care of deciding which LiquidCrystal object to use.
LCDController.h:
#include <LiquidCrystal.h>
class LCDControllerClass
{
 protected:

 public:
        void init(LiquidCrystal* Clcd1, LiquidCrystal* Clcd2);
 private:
   void _UpdateLCD(int _iLine, int _iPosition, String _strText, int _iFieldLength);
   LiquidCrystal* _Clcd1;
   LiquidCrystal* _Clcd2;
};
extern LCDControllerClass LCDController;

My 2 LiquidCrystal objects are initialized in my main .ino file like so (before the setup() loop)
:
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);  //declare two LCD's
LiquidCrystal lcd2(12, 10, 7, 6, 5, 4); // Ths is the second

These two objects are then passed as pointers to my LCDControllerClass like so:
LCDController.init(&lcd, &lcd2);

The init() member method of my LCDControllerClass then puts these pointers in private variables like so:
void LCDControllerClass::init(LiquidCrystal* Clcd1, LiquidCrystal* Clcd2)
{
   _Clcd1 = Clcd1;
   _Clcd1->begin(40, 2);
   _Clcd1->clear();

   _Clcd2 = Clcd2;
   _Clcd2->begin(40, 2);
   _Clcd2->clear();
}

Then I have another private member method which should take care of updating the correct LCD object:
void LCDControllerClass::_UpdateLCD(int _iLine, int _iPosition, String _strText, int _iFieldLength)
{
   LiquidCrystal* CActiveLCD;
   if (_iLine > 2)
   {
      //DisplayLine is higher than 2, this means we need to update the 2nd LCD
      LiquidCrystal** CActiveLCD = &_Clcd2;
      _iLine = _iLine - 2; //Convert line number to correct line number for 2nd display
   }
   else
   {
      //LiquidCrystal** CActiveLCD = &_Clcd1;
   }
   /* we have to convert this number
      to a real display line (0-1) by substracting 1 again
   */
   _iLine = _iLine - 1;

   CActiveLCD->setCursor(_iPosition, _iLine);
   CActiveLCD->print(_strText);
}

Now in this last member mehthor my code goes into the woods for some reason. The LCD is not updated at all and it seems the arduino is freezing as well since I put a small Serial.print() test in the main loop and it's not printing anything...
What is the correct way to pass the correct LiquidCrystal object to the CActiveLCD
object?

The problem is that you're declaring multiple pointer variables called CActiveLCD in the _UpdateLCD() function. You do it once at the start of the function like this:
LiquidCrystal* CActiveLCD;

You then declare a new and totally separate pointer inside the if block like this:
LiquidCrystal** CActiveLCD = &_Clcd2;

This is called masking. The original pointer you declared at the start of the function still exists, but you can't access it because it's temporarily replaced by the new one. When the if block finishes, that new pointer is destroyed (it goes out of scope) and the old one is available again.
All of that means you never actually store a value in the original pointer variable. The result is that it contains an arbitrary memory address, so attempting to use it at the end of the function results in undefined behaviour.
When you are assigning to the pointer inside your if block, you need to do it like this:
CActiveLCD = _Clcd2;

Notice that this doesn't declare a new CActiveLCD pointer. It simply copies _Clcd2 into the existing one. Additionally, it's important not to use the address-of operator here (&). Adding that in this context gives you a pointer-to-a-pointer. It is technically legitimate in C++, and sometimes does serve a useful purpose, but it's not what you want to do here.
As a side note, when declaring a pointer variable it's usually a good idea to initialise it to something. If you're not assigning an actual address to it right away then initialise it to 0, like this:
LiquidCrystal* CActiveLCD = 0;

This means you can check the pointer later on before using it. If it's 0 then you know it's not got a valid address yet so it's not safe to use. This isn't always strictly necessary, but it can help avoid some frustrating bugs.

Thanks a million, your answer solved my problem and explained the reason behind it!


text:
Elegant solution for refreshing TFT display content?
I'm currently drawing black boxes over old content before displaying constantly refreshing content on my display, so for instance to display temperature:
if (sensorTemp != nowTemp){
    nowTemp = sensorTemp;
    tft.fillRect(0,52,88,21,ILI9341_BLACK);
    return nowTemp;
}

If I don't do this the display will just overlay content until it becomes a white blob.
However, this solution leaves me with a black flickering on the display and I can't control exactly what is refreshed where. So for instance when I want to display the current time or date it has to refresh the date all the time, even though nothing changed.
void loop() {
  tft.setTextSize(2);
  tft.setCursor(0,0);
  tft.print(rtc.getDateStr());
  tft.fillRect(144,0,199,15,ILI9341_BLACK); //Black box drawn over 'old' time data
  tft.setCursor(144,0);
  tft.print(rtc.getTimeStr());  //Draw new time
  tft.setCursor(0,52);
  tft.print(tempCall());  //call function to check on temperature and draw new data if necessary
}

Is there a more elegant solution to this problem?

What library are you using? You either want to render your string in an off-screen buffer (which takes lots of memory and library functions that support that kind of thing) or somehow make the characters print the background as well as the foreground colour - and that depends on what library you are using.  The Uno is poorly equipped for working with TFT screens due to lack of memory. It certainly wouldn't be my first choice (it wouldn't even make it on my list at all...)

@Majenko I'm using a Mega with the Adafruit GFX library for ILI9341 tft screens. I am not aware of any other libraries that work with SPI screens, but I haven't done any extensive googling on that yet.

Ah, good. That library is the one I originally based DisplayCore (chipKIT display library suite). It can be done.  I'll explain how...

@Majenko ah! I remember you! You're the guy who told me about SPI like a month ago :)

The Adafruit GFX library has two functions for setting the text colour:
setTextColor(uint16_t c)
setTextColor(uint16_t c, uint16_t bg)

The first sets both the foreground and background to the same colour, and the second to two different colours.  You may ask why you would want the foreground and background to be the same - well, the library handles that situation as a special case: it makes the background transparent.
By setting the foreground and background to different colours you force the library to draw that background colour in over whatever is already on the screen.
tft.setTextColor(ILI93481_WHITE, ILI9341_BLACK);

With that any background pixels in the text string will be coloured black and the text itself white.  As long as the string you are printing is the same length as the text that is already there it will be replaced completely.

Thanks again for your help, this made my whole code a lot easier and displaying data much more elegant.

Should be noted that this only works with the built-in GLCD font. Custom fonts can't be re-drawn in this manner.

If you look in the "Adafruit_GFX.cpp" you will see the following.
void Adafruit_GFX::setTextColor(uint16_t c) {
 // For 'transparent' background, we'll set the bg
 // to the same as fg instead of using a flag
 textcolor = textbgcolor = c;
}

void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
 textcolor   = c;
 textbgcolor = b;
}

If you only want to Draw the Character with a transparent background meaning you only write the character setTextColor in the prescribed pixels changing none of the surrounding pixels in the character block defined by x, y, setTextSize.
TFT.setTextColor(GREEN); //With Transparent Text Background not updating surrounding pixels.

If you want to Draw the Character with your background color, replace app pixels in the character block defined by x, y, setTextSize with your chosen text color and your background to be the same as your chosen background. This will overwrite all pixels with old character that are no longer used with the background color all at the same time preventing mess of pixels, and character flashing.
TFT.setTextColor(GREEN, BLACK); //With Text Background Color updating surrounding pixels.

This code works well and accounts for values of different length.
void textValue() {
  float newValue = @your input@;
  int numChars = String(newValue).length(); // Get the number of characters
  int valueWidth = numChars * 6 * 2.5;

  if (valueWidth != previousValue) {
    tft.fillRect(0, 55, previousValue, 30, ST77XX_BLACK);
    previousValue = valueWidth;
  }
  tft.setCursor(3,60);
  tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
  tft.setTextSize(2.5);
  tft.print(newValue);
}

Hmm the solution is how the code is written...no fancy stuff...the KIWI way
//in setup function add tft.fillScreen(ST7735_GREEN);

void loop(){

  int lightIntensity = myBH1750.getLux();
  tft.setTextSize(3);
  tft.setCursor(10,10);
  tft.setTextColor(ST7735_RED);
  tft.print(lightIntensity);
  delay(3000);
  tft.setTextColor(ST7735_GREEN);
  tft.setCursor(10,10);
  tft.print(lightIntensity);
  tft.setCursor(10,50);
  tft.setTextColor(ST7735_BLUE);
  tft.print("LUX");
}


text:
How do I get status of contactors using Arduino (more than 50 contactors)
I am new to Arduino. Sorry if my question sounds wrong.
Interest areas: Multiple devices inter-connected on the cloud.
Single GSM for equipment in a typical panel connectivity for non-electrical parameter sensing devices e.g. Temperature, humidity.
Mechanical operations & connection status
Parameters of individual devices [non-communication capable]
Connectivity with cloud
Interest areas: Connectivity for electromechanical devices – Contactors, MCBs, RCCB etc
Parameters possible on IOT
Device Status possible on IOT
Size [Compactness] of the IOT solution to be integrated
Aux Power requirement & possible ways to provide the same
Memory retention
Remote access/control and driving of the devices
The estimated cost of the IoT connectivity devices should be a fraction of the device cost [e.g. Contactor of 9A].
Voltage level high
I am trying to read the status of more than 50 contactors i.e whether they are in ON\OFF\trip state using Arduino and display it on screen.
Can I use a single microcontroller to read the status of 50 or more contactors?
I searched on the net and I found out it can be done using shift registers or a latching system, but I didn't understand the method at all.
Please, can anyone explain me the method of doing this?Thanks.

Comments are not for extended discussion; this conversation has been moved to chat.

Due to lack of specifics, I cannot be more precise with my answer, but since you are working with "high" voltage (I'll assume 220V/415V) I would suggest the best solution to monitoring the current will be current transformers.
These are non-intrusive devices that you pass a single conductor through. It generates a small current in proportion to a large current flowing through the conductor.
This small current is then converted into a small voltage by passing it through a resistor and then measuring the voltage across that resistor.
Since it is AC you are dealing with simple digital IO pins will not suffice (except see below) - no matter how many you have. You need analog inputs, and you need to be able to sample that analog signal fast enough to at least capture the peaks and troughs of the incoming waveform. That means sampling at many times the frequency of the supply. For 50Hz you want to sample either at, say, 500 sps or more, or to sample at a rate that isn't a multiple of, or factor of, 50, but for a longer period of time.
Interfacing an AC voltage like this involves adding an offset voltage to it so that the zero point of the AC voltage lies in the middle of the ADC's range. This is most often done by feeding a voltage of 50% Vcc into the current transformer as a "virtual ground", so all output from it is superimposed on this offset voltage.

simulate this circuit – Schematic created using CircuitLab
Once you know the peak to peak voltage across the load resistor of the current transformer you can use that to calculate the peak to peak current the current transformer generated (Ohm's law), and thus the current through the central conductor.
This not only gives you the actual current through the conductor, but by simple logical reasoning, also gives you the state of the contactor: no current = contactor is off.
To reduce programming complexity at the cost of increased BOM cost it could be possible to build a simple rectifying and smoothing circuit (i.e., a simple integrating circuit) from diodes and a capacitor (either a single diode and a capacitor as a half-wave rectifier and smoothing, or a full-wave rectifier and smoothing) which will give you a simple DC voltage proportional to the current. Don't forget to take into account the voltage drop of the diode (or diodes) when doing your calculations, of course.
The integrating circuit could also be used, if you don't care about the current, to directly drive a digital input, as long as the voltage generated under normal load is above the threshold (VIH) of the IO pin, and never exceeds the maximum input voltage for the pin (a little over 5V).  Adding a 5.1V zener diode and series resistor can help protect the input. The same should be done to an analog input as well to protect it from overvoltage.

simulate this circuit
One important thing with this integrating circuit, though, is that any downward changes in the current will take time to be reflected in the output. That is caused by the time C1 takes to discharge down to the new voltage level through R1. Balancing these values so you get a reasonable amount of responsiveness yet minimum amount of ripple on the signal will take a little experimentation and calculation.
You can read more about current transformers and interfacing them to an Arduino here.

For interfacing so many sensors to an Arduino you can, depending on if you are wanting to measure the current directly, or integrate the current to a DC voltage and use it as a threshold to a GPIO pin:

Use shift registers (Parallel-to-Serial) for digital threshold reading,
Use IO expanders (eg MCP23017) for digital threshold reading,
Use external ADC chips (eg MCP3208) to provide more ADC inputs, or
Use analog multiplexers (eg CD4051) to switch different analog voltages to a limited number of ADC inputs

Another option is to break your system down into smaller, more manageable, chunks.  Group your signals into small subsections and have each subsection handled by a separate controller - be that an Arduino (maybe a Mini, or a Micro, or something) to handle a small group of signals. These can then feed their data into a more powerful management system (maybe a Raspberry Pi) through a serial protocol of some form (or wirelessly if you want to spend extra money), which then forwards the readings on to your chosen web service.

Yes you can.
There are special ICs, called Shift-In registers to do this job. You can daisy chain 4 of them, each capable of handling 8 outputs or inputs.
The most known is for outputs (e.g. LEDs) which is a 74HC595 (called shift-out register).
For inputs. you can use a CD4021BE. See the Shiftin Example how to use them.
It will cost 3 pins (except VCC/GND) to control 32 inputs, so you need 6 pins for 50 (max 64). You need 50 / 8 = 7 of these ICs, but they are very cheap (10 for about 2 dollars).
Note that you will receive either a 0 or 1, so it's up to you how to detect trip states.

Thanks! can I also read current or voltage using shift register plus some more circuitry?

No, you only get digital signals (0 or 1). I'm not aware of voltage (analog) readings... in that case you might need ADC converters probably. The Uno has 5, if you need more, you need a chip that has multiple ADC channels, but I don't have experience with that.


text:
Why my loop stop working
i have an arduino, an RTC (time), a DHT (humidity and temp sensor), oled screen (128x32 ; microoled 1306) and 4 relais ;
all seems to work perfectly for hours, but sometime (1 or 2 per day..) everything stop working ;

screen i frozen on last info displayed
relais stay stuck in a random position (somtimes turning everythings ON (on=LOW with thoses relay.))

i obviously made a mistake, but don t know what...
what can cause a loop to stay stuck randomly ???
plz save me :)
EDIT => A REWORK OF THAT TERRIBLE CODE AVAILABLE IN ANSWER, THE PROBLEM IS STILL THERE
// GND GND
// A4 SCL
// A5 SDA
// VCC  5V

// for DHT11,
//      VCC: 5V or 3V
//      GND: GND
//      DATA: A7+

// YL-39 + YL-69 humidity sensor
const byte humidity_sensor_pin = A1;
const byte humidity_sensor_vcc = 6;

// ecran SDA / SDL
// RELAIS Pin D8
// RELAIS2 Pin D9
// RELAIS3 Pin D10
// RELAIS4 Pin D11

// Relais reboot D5 ?

#include <SimpleDHT.h>
#include <Wire.h>
#include "U8glib.h"
#include "RTClib.h"

const int pinDHT11 = 7;
 SimpleDHT11 dht11;

RTC_DS1307 RTC;
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);

const int relay = 8; // Light
const int relay2 = 9; // Wind
const int relay3 = 10; // Heat
const int relay4 = 11; // Humidity

// Time Variable
DateTime InitTime ;
int InitHour;

const int startHour = 20;
const int startMin = 01;
const int startTime = startHour *100 + startMin;
const int endHour = 8;
const int endMin = 01;
const int endTime= endHour *100 + endMin;
const int maxWind = 5;
const int startWind = 05;
int lastWind ;

const int dayMinTemp = 18;
const int dayMaxTemp = 20;
const int nightMinTemp = 16;
const int nightMaxTemp = 19;

const int minhum = 50;

void drawInit(DateTime InitD){
String text = String(InitD.day());
  text += " ";
text += String(InitD.month());

String text2 = String(InitD.hour());
  text2 += ":";
text2 += String(InitD.minute());
text2 += ":";
text2 += String(InitD.second());

 u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(0,16);
  u8g.print(text);
  u8g.setPrintPos(0,32);
  u8g.print(text2);

}
void drawTemp(float temp, int hum, int nowT){
String text = "Temp: ";
  text += temp;
    text += "*C";
String text2 = "Hum: ";
  text2 += hum;
    text2 += "% :";
    text2 += nowT;

 u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(0,16);
  u8g.print(text);
  u8g.setPrintPos(0,32);
  u8g.print(text2);
}

void draw(String staT, String endT, String nowT){
String iotxt;
if (digitalRead(relay) == LOW){iotxt="On";}else{iotxt="Off";}

String text = "S: ";
  text += staT;
  text += " E: ";
  text += endT;
String text2 = "H: ";
  text2 += nowT;
//  text2 += " L: ";
//  text2 += iotxt;

  u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(0,16);
  u8g.print(text);
  u8g.setPrintPos(0,32);
  u8g.print(text2);
}

void drawerror(String error){
  String text = "err mod: ";
  text += error;

  u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(0,16);
  u8g.print(text);

}

void draw2(int nowTime){
  String iotxt;
  String hottxt;
  String lumtxt;
    String humtxt;

if (digitalRead(relay) == LOW){lumtxt="On";}else{lumtxt="Off";}
if (digitalRead(relay2) == LOW){iotxt="On";}else{iotxt="Off";}
if (digitalRead(relay3) == LOW){hottxt="On";}else{hottxt="Off";}
if (digitalRead(relay4) == LOW){humtxt="On";}else{humtxt="Off";}

String text = "Hot: ";
  text += hottxt;
  text += " Lum: ";
  text += lumtxt;

String text2 = "Hum: ";
  text2 += humtxt;
  text2 += " Win: ";
  text2 += iotxt;

  u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(0,16);
  u8g.print(text);
  u8g.setPrintPos(0,32);
  u8g.print(text2);
}

void setup () {

 pinMode(relay, OUTPUT);
 pinMode(relay2, OUTPUT);
 pinMode(relay3, OUTPUT);
 pinMode(relay4, OUTPUT);
 digitalWrite(relay, HIGH);
 digitalWrite(relay2,HIGH);
 digitalWrite(relay3,HIGH);
 digitalWrite(relay4,HIGH);

    Serial.begin(9600);
    Wire.begin();

    if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  RTC.begin();

   DateTime now = RTC.now();
 InitTime = now ;
InitHour =  now.hour()*100 + now.minute();
}

void loop () {

 byte temperature = 0;
  byte humidity = 0;

int err = SimpleDHTErrSuccess;
  if ((err = dht11.read(pinDHT11, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
//    Serial.print("Read DHT11 failed, err="); Serial.println(err);delay(1000);

    u8g.firstPage();
  do {
    drawerror("DHT");
  } while( u8g.nextPage() );
delay(3000);

    return;
  }else{

  // Serial.print("Sample OK: ");
 // Serial.print((int)temperature); Serial.print(" *, ");
 // Serial.print((int)humidity); Serial.println(" H");

// Relay Chaleur
if (digitalRead(relay)==LOW){
if((int)temperature < dayMinTemp){
   digitalWrite(relay3,LOW);
   //  Serial.print("HEAT : On");

  }else{digitalWrite(relay3,HIGH);
     //  Serial.print("HEAT : Off");
}
  }else{
    if((int)temperature < nightMinTemp){
   digitalWrite(relay3,LOW);
     //   Serial.print("HEAT : On");

}else{
      digitalWrite(relay3,HIGH);
   //  Serial.print("HEAT : Off");

      }
    }
// fin relay chaleur

  if (! RTC.isrunning()) {
    drawerror("RTC");}else{

   DateTime now = RTC.now();

int nowTime= now.hour()*100 + now.minute();

// § WIND
if(now.minute() >= startWind && now.minute() <= startWind+maxWind ){
      digitalWrite(relay2,LOW);
     // Serial.println("Wind ON");
      lastWind = nowTime;

  }else if(now.minute()>startWind+5 || now.minute()<startWind){
          digitalWrite(relay2,HIGH);
    //  Serial.println("Wind OFF");
      }

// § END WIND

// START humidity
if(int(humidity)<minhum){
      digitalWrite(relay4,LOW);

  }else{    digitalWrite(relay4,HIGH);
  }
//
// § LIGHT START

if(startTime<endTime){
  if(startTime <= nowTime && endTime >= nowTime){
      digitalWrite(relay,LOW);
    //  Serial.println("Light ON");
  }else{
      digitalWrite(relay,HIGH);
//      Serial.println("Light OFF");
}}else{
  if(endTime <= nowTime && startTime >= nowTime){

      digitalWrite(relay,HIGH);
  //    Serial.println("Light OFF");
  }else{
          digitalWrite(relay,LOW);
    //  Serial.println("Light ON");
    }}

//  if(nowTime >= startTime && nowTime <= 2359){
//            digitalWrite(relay, LOW);
//            Serial.println("Light ON");
//            }
//       else if(nowTime  < endTime ){
//            digitalWrite(relay, LOW);
//            Serial.println("LIGHT ON");}
//       else if(nowTime  >= endTime && nowTime  < startTime){
//            digitalWrite(relay, HIGH);
//            Serial.println("Light OFF");}
//      }
      // § LIGHT END

u8g.firstPage();
  do {
    draw(String(startTime),String(endTime),String(nowTime));
  } while( u8g.nextPage() );
delay(3000);

u8g.firstPage();
  do {
    drawInit(InitTime);
  } while( u8g.nextPage() );
 delay(3000);

u8g.firstPage();
  do {
    draw2(nowTime);
  } while( u8g.nextPage() );
 delay(3000);
u8g.firstPage();
  do {
    drawTemp(float(temperature), int(humidity),int(NowT));
  } while( u8g.nextPage() );
 delay(3000);
    }}}

you may want to fix your identation, that will help clarify the logic flow of each function

At a quick guess I'd say your heap is swiss cheese. Ditch String.

i will rework that to made it more digest xD sry, let me few min :)

@Look Alterno  : thx i will check this and implement it :)

your code is horribly formatted ... it is a mess ... it is very difficult to determine how all the parts interact

@jsotola : u are totaly alright, i rewrite it totaly, hoping the same hlp, don t hesitate to bring me comments on the new one, :) (if problem there is, try to give me some tips :) i m a nooby amateur dev. )

While it makes logical sense to use the String type to hold strings of text, it's really a very poor choice for a low-RAM device like an Arduino.
You are using the string concatenation operator (+) a lot. The String type handles this by grabbing a new block of RAM that is equal to the sum of the 2 strings you are concatenating, puts the new string in that RAM, and marks the previous block of RAM that held one of the strings as empty and available for re-use.
The problem is that when you keep concatenating bits to the same string variable, it has to keep finding longer and longer continuous blocks of RAM into which to put the new string. All the previous blocks that are "available" for use, are also too short, as they are all the length of previous strings prior to your new, longer string requirement.
As @Majenko noted, this means your RAM is "swiss cheese" -- full of holes that can't be used by the program for more strings.
One solution is to avoid the String variable type and instead use what are called C-Style Strings - arrays of char type. It's a whole new, old world of doing things, and can be more challenging than the String type, but it has a distinct advantage of not shredding the device's RAM.
The C-style string world is ruled by monsters like strnlen() and strncpy(), and making sure you have remembered to allocate enough RAM at the start of your program, and making sure you null-terminate your array.
Of the myriad tutorials and descriptions on using C-style strings, one is at https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/

No, but often some other action takes place that puts another block on the heap.

That s seem s realy logical ! i will dig this and apply the change :)

arf, till a small problem, i don t achieve to concat in any way my char[] and my INT :/
char screen[16] ;
char text[3] = "abc" ;
int i = 12 ;
screen[16] = text + i ;

You can't use + to concat c-style strings. Use strncat().

Also, you'll need to convert your int to a char[] (C-style string) using something like itoa()

@jose can u c : yep, the conversion put me in mess few hours :) but i think i deal with it, it probably can be improve anw, but sadly, the problem remains...

after rewrite all code, rewire all relay, bypass the relay card (using another relay), the problem is still there, but i finally found other people with the same problem, and the solution seem to be adding a "snubber" on each relay, i m waiting for it and will give u a return if it work :
link to arduino forum for a common problem


text:
Arduino blocks when serving web pages
I have an Arduino sketch that serves an HTML web page using the standard Ethernet library (https://github.com/arduino-libraries/Ethernet) and the Ethernet Web Server library (https://github.com/khoih-prog/EthernetWebServer). I am serving HTML stored directly in the Arduino memory. The processor is the ARM Cortex M0+. Here is an extract from the code I am using:
#include <Ethernet.h>
#include <EthernetWebServer.h>

#define webpage "Big HTML string"

EthernetWebServer webServer;
void setup()
{
  SerialUSB.begin(9600);

  Ethernet.begin(settings.macAddress, settings.ipAddress, settings.ipAddressDns, settings.ipAddressGateway, settings.ipAddressSubnet); // 'settings' is a struct declared elsewhere
  webServer = EthernetWebServer(settings.portHttp);

  webServer.on("/login", [&webServer]{ // /login handler
    webServer.send(200, "text/html", webpage);
  });
}

void loop()
{
  webServer.handleClient();
}

When I refresh the page (send GET request) more than 9 times or so the Arduino freezes. I have checked by placing SerialUSB.println() inside the code and it seems to stop before even entering the "/login handler" callback.
Does anyone know the cause or at least how to solve this?

the EthernetWebServer library is very new. create an issue in the GitHub repository


text:
Can the arduino be recognized if the usb chip is broken?
My question might seem one of the million questions out there "Can't upload to arduino uno and receive error avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x01" but as I probably read all the million questions and didn't find the answer I am looking for I decided to write my own.
So my arduino is properly detected in device manager and in the arduino IDE but cant upload sketches to it. The main chip (atmega328p) seems well (13-pin LED blinks 3 times on reset) but the usb chip (ATmega16u2) is what I suspect as the RX and TX LEDs don't blink while uploading (and don't blink in any other situation) but again the arduino is detected and I am sure I chose the right board and port.
The serial monitor is always empty and I tried the loopback test and didn't get any echo at all or even any error message but I think that what I should have expected as the RX and TX not blinking means that there is no data transmission in the first place. Or am I wrong?
So is the USB chip broken or maybe corrupt? How can I be sure? And if not then what could the problem be?
I saw a tutorial in the answer of this question to test the usb chip using another arduino but I don't have that in hand right now or an ICSP programmer for that matter.

Have you tried the loopback test? Short TX and RX together on the Arduino, open the serial monitor, and see if you get back whatever you send?

Oh I forgot to mention that. I will edit the question to include it.

It could be dead, yes. Or the firmware may be corrupt. Try reflashing it with dfu: https://www.arduino.cc/en/Hacking/DFUProgramming8U2

But how can it be dead and the arduino is still detected? I am not arguing I really want to know and I am very new to this field.

@Majenko By the way thanks so much for that link. It is more detailed that any other source I found.

It sounds like the GPIO portion of the chip may be dead.  There is an unconfirmed (it's purely anecdotal at the moment) possibility that shorting 5V on an Uno can kill the U2. I don't know the full effects of it yet, but it could be related.

A microcontroller is like a car. Internally there's lots and lots of different sections, all fairly independent. Just like a car, if someone nicks the wheels it's still recognisably a car. The doors still open, the engine still runs, the radio works - you just can't get it to move any more.

It depends on the exact arduino product. An Arduino Uno has a USB programmer chip, that then programs the AtMega 328 Chip. If the programmer is broken, it will likely not register any device when you plug in an arduino uno to your PC.
if the micro-controller is dead, but the programmer is operational, you will get a device in your device manager, but not be able to reprogram the micro controller.
If both the programmer, and the micro-controller are broken, then figuting that out could be difficult. The AVR microcontrolers support other programing methods, and the AtMega 328 IC, supports DebugWire. you could attempt to reprogram the MCU out side of the programmer, if you thought the programmer, was defective.
Here is a great article on using DeBugWire.
https://awtfy.com/2010/02/21/modify-an-arduino-for-debugwire/
another nifty trick I learned, is to take your Digital MultiMeter, set it to diode test, or continuity. then, measure between the ground pin, and the positive voltage pins on the MCU.  If you get a shot, the chip is busted. You will expect to get roughly 0.7Volts, although an OL reading might indicate more about your multi-meter, than the MCU.
Other Arduino devices, that have integrated USB programing, may behave differently. Features of the specific MCU dictate how it can be debugged. You might want to read the datasheet for a specific MCU if you're having trouble.

I'm quite confident that the problem is not with the main chip but can you provide more detail on how to perform that test with the multimeter and what to expect in both cases.

Ground to VCC expect to get 0.5v, to 0.7 volts on a diode test. Short is a certain failed chip, and Open, is suspicious.