ESP32 weatherstation - migrating from WiFi to W5500 ethernet

Hi,
I hope somebody can help.
I've been building a weather station for a remote site using an ESP32 Wrover Dev kIt.
I've got it working the way I want but now have to chenge from WiFi to Ethernet due to site limitations, and can I get it to work??? No!

I have the w5500 connected correctly and using this sketch it connects to the network and can be pinged.

#include <Ethernet.h>
#include <WiFi.h>

#define ETH_SPI_SCS   5   // CS (Chip Select), Green

uint8_t baseMac[6];


void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("Starting Ethernet connection...");

  //Set the CS pin, required for ESP32 as the arduino default is different
  Ethernet.init(ETH_SPI_SCS); 

  
esp_read_mac(baseMac, ESP_MAC_ETH);
Serial.print("Ethernet MAC: ");
for (int i = 0; i < 5; i++) 
  {
  Serial.printf("%02X:", baseMac[i]);
  }
Serial.printf("%02X\n", baseMac[5]);

  //Start the Ethernet connection
  Ethernet.begin(baseMac);

    //Hardware check
  Serial.println("Checking Ethernet hardware...");
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("ERROR: No Ethernet hardware detected!");
    return;
  }
  else {
    Serial.println("Ethernet hardware detected!");
  }

  //Check if cable is connected
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Link is OFF. Check cable connection.");
  }
  else {
    Serial.println("Link is ON. Cable is connected. Ready to go!");
     Serial.println("DHCP OK!");
    Serial.print("Local IP : ");
    Serial.print("To test connection, please ping: ");
    Serial.println(Ethernet.localIP());
    Serial.println("Using hardwired ethernet");
  }

}

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

}

This uses the ESP's WiFi MAC address as the ethernet MAC (they'll never be used together) and DHCP works BUT when I convert the main sketch to Ethernet it compiles but cant get the time and goes no further..
I'm no programmer so please be gentle with me if I've made stupid errors..


#include <Arduino.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <WiFi.h>
#include <SPI.h>
#include <Wire.h>
#include <time.h>
#include <HTTPClient.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <I2C_LCD.h>
//#include "Adafruit_SSD1306.h"    
#include "Adafruit_GFX.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ZMPT101B.h>
#include <ThingSpeak.h>

#define SENSITIVITY 500.0f
#define ETH_SPI_SCS   5   // Ethernet CS (Chip Select)

//#define SCREEN_WIDTH 128 // OLED display width, in pixels
//#define SCREEN_HEIGHT 32 // OLED display height, in pixels
//#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
//#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
//Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//#define SEALEVELPRESSURE_HPA (1013.25)

//ZMPT101B sensor output connected to ADC pin 34
// and the source freq is 50 Hz
ZMPT101B voltageSensor(36, 50.0);

Adafruit_BME280 bme;              // I2C
unsigned long delayTime;

int t = 0;

// GPIO 17 where the relay is connected
const int relay = 26;  // 26 is relay control


// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 1000;    // the debounce time; increase if the output flickers 

int pinInterrupt = 15; 

int Count=0;

int wspdcms = 0;
int wspdmph = ((Count*8.75)*0.0223694);
/////////////////////////////////////////////////

// GPIO where the DS18B20 is connected to
const int oneWireBus = 27;     

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);

// Change to your WiFi credentials and select your time zone
//const char* ssid     = "your_SSID";
//const char* password = "your_PASSWORD";



EthernetClient client;

unsigned long myChannelNumber = xxxxxxx;
const char * myWriteAPIKey = "yyyyyyyy";

// Timer variables
unsigned long lastTime = 0;
//unsigned long timerDelay = 600000;
unsigned long timerDelay = 60000;

I2C_LCD lcd(39);

const char* Timezone = "GMT0BST,M3.5.0/01,M10.5.0/02";  // UK, see below for others and link to database
String      Format   = "X";       // Time format M for dd-mm-yy and 23:59:59, "I" for mm-dd-yy and 12:59:59 PM, "X" for Metric units but WSpeed in MPH

uint8_t baseMac[6];


static String         Date_str, Time_str;
volatile unsigned int local_Unix_time = 0, next_update_due = 0;

volatile unsigned int update_duration = 60 * 30; // Time duration in seconds, so synchronise every halfhour
static float          bme_temp, bme_humi, bme_pres, WindSpeed;// temperatureC;
static unsigned int   Last_Event_Time;

//#########################################################################################

void IRAM_ATTR Timer_TImeout_ISR() 
{
  portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
  portENTER_CRITICAL_ISR(&timerMux);
  local_Unix_time++;
  portEXIT_CRITICAL_ISR(&timerMux);
}

//#########################################################################################
void onChange()
{
   if ( digitalRead(pinInterrupt) == LOW )
      Count++;
}

//#############################################

void setup() 
{
  Serial.begin(115200);
  pinMode (relay, OUTPUT);
  
  StartEthernet();
  
// Windspeed setup
  pinMode( pinInterrupt, INPUT_PULLUP);// set the interrupt pin

//Enable
  attachInterrupt( digitalPinToInterrupt(pinInterrupt), onChange, FALLING);
//######################### 
  
  // Set configurations before initialization
  
  // Start the DS18B20 sensor
  sensors.begin();
  voltageSensor.setSensitivity(SENSITIVITY);
  
   //ThingSpeak.begin(client);  // Initialize ThingSpeak
   
  Wire.begin(SDA, SCL, 100000);       // (sda,scl,bus_speed) Start the Wire service for the OLED display using pin=D4 for SCL and Pin-D3 for SDA
  
  bool status = bme.begin(0x76);                 // For Adafruit sensors use address 0x77, for most 3rd party types use address 0x76
  if (!status) Serial.println("Could not find a valid BME280 sensor, check wiring!"); // Check for a sensor
  lcd.begin(20,4); 
  lcd.display();
  lcd.clear();
  //display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //display.clearDisplay();
  //display.setTextColor(WHITE);
 
  
  

   ThingSpeak.begin(client);  // Initialize ThingSpeak
   
  delay (2000);

  

   
  Start_Time_Services();
  Setup_Interrupts_and_Initialise_Clock();       // Now setup a timer interrupt to occur every 1-second, to keep seconds accurate
 /* for (int index = 0; index < WS_Samples; index++) 
    { // Now clear the Wind Speed average array
    WSpeedReadings[index] = 0;
    }
 */
}
//#########################################################################################
void loop() 
  {
  sensors.requestTemperatures(); // Gets External Temp
  
  UpdateLocalTime();     // The variables 'Date_str' and 'Time_str' now have current date-time values
 
  BME280_Read_Sensor();  // The variables 'bme_temp', 'bme_humi', 'bme_pres' now have current values

 
  float temperatureC = sensors.getTempCByIndex(0);
  float temperatureF = sensors.getTempFByIndex(0);

  
// AC Voltage detector

  float ACvoltage = voltageSensor.getRmsVoltage();
  Serial.println(ACvoltage);
  if (ACvoltage < 180)
      {
      //digitalWrite(relay, HIGH);  //relay = high;
      Serial.println("Low AC Voltage");
      }

    else 
      {
        //digitalWrite(relay, LOW);
      }
      
      
 // Windspeed calculations     
   if ((millis() - lastDebounceTime) > debounceDelay) 
      {
    lastDebounceTime = millis();
    wspdcms=(Count*8.75);
    
    wspdmph=((Count*8.75)* 0.0223694);
    Serial.print(wspdmph);
    Count=0;
    Serial.println("mph");
    }

    
    //display.clearDisplay();
    //display.setTextSize(1);
    //display.setCursor(0,0);
    //display.print(Date_str);     // Display current date
    //display.setCursor(70,0);
    //display.print(Time_str); 
    

    
    lcd.setCursor(0, 0);
    lcd.print(Date_str);
    lcd.setCursor (12, 0);
    lcd.print(Time_str);
    
    lcd.display();
    //display.display();

    
   /* display.setCursor (5,10);
    display.print(bme.readTemperature());
    display.print("c");
    display.setCursor (75,10);
    display.print(bme.readHumidity());
    display.print("%");
    display.setCursor(10,24);
    display.print(temperatureC);
    display.print("c");
*/

    lcd.setCursor(0, 1);
    lcd.print("T");   
    lcd.setCursor(2, 1);
    lcd.print(bme.readTemperature());
    lcd.print("c");
    lcd.setCursor(12, 1);
    lcd.print("H");
    lcd.setCursor(14, 1);
    lcd.print(bme.readHumidity());
    lcd.print("%");
   
    lcd.setCursor(6,2);
    lcd.print("External");
    lcd.setCursor(0,3);
    lcd.print("T ");
    lcd.setCursor(2,3);
    lcd.print(temperatureC);
    lcd.print("c");
    lcd.setCursor(12,3);
    lcd.print("W");
    lcd.setCursor(14,3);
    lcd.print("        ");
    lcd.setCursor(14,3);
    lcd.print(wspdmph);
    
    lcd.display();
    //display.display();
    
 
  
  

GoToT_Spk();

  delay(5000);                                                                                                         // Small arbitrary delay
}
//#########################################################################################
void UpdateLocalTime() 
{
  time_t now;
  if (local_Unix_time > next_update_due) 
  { // only get a time synchronisation from the NTP server at the update-time delay set
    time(&now);
    Serial.println("Synchronising local time, time error was: " + String(now - local_Unix_time));
    // If this displays a negative result the interrupt clock is running fast or positive running slow
    local_Unix_time = now;
    next_update_due = local_Unix_time + update_duration;
  } 
    else now = local_Unix_time;
  //See http://www.cplusplus.com/reference/ctime/strftime/
    char hour_output[30], day_output[30];
  if (Format == "M" || Format == "X") 
  {
    strftime(day_output, 30, "%d-%m-%y", localtime(&now)); // Formats date as: 24-05-17
    strftime(hour_output, 30, "%T", localtime(&now));      // Formats time as: 14:05:49
  }
  else 
  {
    strftime(day_output, 30, "%m-%d-%y", localtime(&now)); // Formats date as: 05-24-17
    strftime(hour_output, 30, "%r", localtime(&now));      // Formats time as: 2:05:49pm
  }
  Date_str = day_output;
  Time_str = hour_output;
 
}
//#########################################################################################
void StartEthernet()
  {
    Serial.println("Starting Ethernet connection...");

  //Set the CS pin, required for ESP32 as the arduino default is different
  Ethernet.init(ETH_SPI_SCS); 

  
esp_read_mac(baseMac, ESP_MAC_ETH);
Serial.print("Ethernet MAC: ");
for (int i = 0; i < 5; i++) 
  {
  Serial.printf("%02X:", baseMac[i]);
  }
Serial.printf("%02X\n", baseMac[5]);

  //Start the Ethernet connection
  Ethernet.begin(baseMac);

    //Hardware check
  Serial.println("Checking Ethernet hardware...");
  if (Ethernet.hardwareStatus() == EthernetNoHardware) 
    {
    Serial.println("ERROR: No Ethernet hardware detected!");
    return;
    }
  else 
    {
    Serial.println("Ethernet hardware detected!");
    }

  //Check if cable is connected
  if (Ethernet.linkStatus() == LinkOFF) 
    {
    Serial.println("Link is OFF. Check cable connection.");
    }
  else 
    {
    Serial.println("Link is ON. Cable is connected. Ready to go!");
    Serial.println("DHCP OK!");
    Serial.print("Local IP : ");
    //Serial.print("To test connection, please ping: ");
    Serial.println(Ethernet.localIP());
    Serial.println("Using hardwired ethernet");
    Serial.print("Gateway IP : ");
    Serial.println(Ethernet.gatewayIP());
    Serial.print("DNS Server : ");
    Serial.println(Ethernet.dnsServerIP());
    }

}
  
//###################################################################

/*void StartWiFi() 
{
  
  WiFi.mode(WIFI_STA);
  Serial.print(F("\r\nConnecting to: ")); Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED ) {
    delay(500);
    Serial.print(F("."));
  }
  Serial.print("WiFi connected to address: "); Serial.println(WiFi.localIP());
 

  
}*/
//#########################################################################################
void Setup_Interrupts_and_Initialise_Clock() 
{
  hw_timer_t * timer = NULL;
  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &Timer_TImeout_ISR, true);
  timerAlarmWrite(timer, 1000000, true);
  timerAlarmEnable(timer);
  
  //Now get current Unix time and assign the value to local Unix time counter and start the clock.
  struct tm timeinfo;
  while (!getLocalTime(&timeinfo)) 
  {
    Serial.println(F("Failed to obtain time"));
  }
  time_t now;
  time(&now);
  local_Unix_time = now + 1; // The addition of 1 counters the NTP setup time delay
  next_update_due = local_Unix_time + update_duration;

  

}
//#########################################################################################
void Start_Time_Services() 
{
  // Now configure time services
  configTime(0, 0, "pool.ntp.org", "time.nist.gov");
  setenv("TZ", Timezone, 1); // See below for other time zones
  delay(1000); // Wait for time services
  
}
//#########################################################################################
void BME280_Read_Sensor() 
{
  if (Format == "M" || Format == "X") bme_temp = bme.readTemperature(); 
    else bme_temp = bme.readTemperature() * 9.00F / 5.00F + 32;
 // if (Format == "M" || Format == "X") bme_pres = bme.readPressure() / 100.0F + pressure_offset;
    //else bme_pres = (bme.readPressure() / 100.0F + pressure_offset) / 33.863886666667; // For inches
  bme_humi = bme.readHumidity();
}
//###########################################################
void GoToT_Spk()
{
ThingSpeak.setField(1, bme.readTemperature());
ThingSpeak.setField(2, bme.readHumidity());
ThingSpeak.setField(3, sensors.getTempCByIndex(0));
ThingSpeak.setField(4, (wspdmph));

if ((millis() - lastTime) > timerDelay) 
    {
    // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
    // pieces of information in a channel.  Here, we write to field 1.
    int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
    //uncomment if you want to get temperature in Fahrenheit
    //int x = ThingSpeak.writeField(myChannelNumber, 1, temperatureF, myWriteAPIKey);

    if(x == 200){
      Serial.println("Channel update successful.");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(x));
    }
    lastTime = millis();
  }
}
//############################################################

// * Example time zones see: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
//const char* Timezone = "GMT0BST,M3.5.0/01,M10.5.0/02";     // UK
//const char* Timezone = "MET-2METDST,M3.5.0/01,M10.5.0/02"; // Most of Europe
//const char* Timezone = "CET-1CEST,M3.5.0,M10.5.0/3";       // Central Europe
//const char* Timezone = "EST-2METDST,M3.5.0/01,M10.5.0/02"; // Most of Europe
//const char* Timezone = "EST5EDT,M3.2.0,M11.1.0";           // EST USA
//const char* Timezone = "CST6CDT,M3.2.0,M11.1.0";           // CST USA
//const char* Timezone = "MST7MDT,M4.1.0,M10.5.0";           // MST USA
//const char* Timezone = "NZST-12NZDT,M9.5.0,M4.1.0/3";      // Auckland
//const char* Timezone = "EET-2EEST,M3.5.5/0,M10.5.5/0";     // Asia
//const char* Timezone = "ACST-9:30ACDT,M10.1.0,M4.1.0/3":   // Australia

Bob

When posing a problem, we like to see the minimum reproducible setup. In this case, the weather station has nothing to do with the wifi, so strip out all that code and leave only the Ethernet setup and connect. That will be a lot less code for us to look at.
BTW, I am skeptical re your comment on MAC. Make sure, show proof.

1 Like

Post an annotated schematic showing exactly how you have wired this, include all connections, power, ground and power sources. Post links to technical information on the hardware devices.

1 Like

You will at least need a schematic to document your system or it will be unmaintainable.

Changing a program from one microcontroller to another is "interesting". You need to reexamine all your assumptions.

if using ethernet with the ESP32 have a look at the wt32-eth01
with the ESP32 and ethernet module on one PCB saves using interconnecting wires which can give poor connections and intermittent problems

Unfortunately its the weatherstation code thats not working..

As for ESP 32 mac addresses,
The esp32 WiFi is allocated a unique mac address by Expressif at manufacture and this can be read according to this note from the documentation:

https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/system/misc_system_api.html#mac-address

MAC Address

These APIs allow querying and customizing MAC addresses for different supported network interfaces (e.g., Wi-Fi, Bluetooth, Ethernet).

To fetch the MAC address for a specific network interface (e.g., Wi-Fi, Bluetooth, Ethernet), call the function esp_read_mac().

The W5500 can be used as per the first sketch given, it gets dhcp and is contactable via ethernet, the problem is why, using the main sketch, can it not get a time update?

The W5500 is connected as follows:

  • 3.3 to external power
  • Miso to esp 19
  • Mosi to esp 23
  • Scs to esp 5
  • Sclk to esp 18
  • Int to esp 25
  • Gnd to psu gnd (common to 5v and 3.3v supplies)
1 Like

You have ignored posts #2, #3, #4

It's obvious you are not a programmer, so where did you get the code from that you probably modified as I see many shall we say interesting things.

BTW, I checked 3 Ethernet library examples, and NOT one messed with the MAC.

I have others to assist who follow the rules, so I will bid you adieu.

It appears you are not interested is solving your problem. Without the schematic I will let you figure this out by yourself. Hint: I do not read frizzes very well.