IoT weatherstation

Hello everyone
I own a weather station at home. The weather station has its own program (CumulusMX), where I can read the various weather data. Now I want to make (part of) the weather data visible on LCD screen (16.2). I've gotten to the point where the Arduino MKR WIFI 1010 is connected to the weather station via MQTT. The most important topic concerns the weather forecast: CumulusMX/Forecast arrives. I get to read this weather forecast on the serial monitor:

Received a message with topic 'CumulusMX/Forecast', length 74 bytes:
Af en toe neerslag, verslechtering weer beeld - Occasional rain, worsening

However, I can't seem to get the topic "CumulusMX/Forecast" on the second line of LCD screen. The first line works: "Weather forecast: ".
Can anyone help me to get the above topic on the LCD screen. As for the hardware: Arduino MKR WIFI 1010 - Grove LCD RGB Backlight – Arduino MKR connector carrier.
The software so far:

#include <Wire.h>
#include <rgb_lcd.h>

rgb_lcd lcd;

#include <ArduinoMqttClient.h>
#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_AVR_UNO_WIFI_REV2)
#include <WiFiNINA.h>
#elif defined(ARDUINO_SAMD_MKR1000)
#include <WiFi101.h>
#elif defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_GIGA)
#include <WiFi.h>
#endif

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
#define SECRET_SSID "xxxxx"
#define SECRET_PASS "yyyyy"
char SSID[] = SECRET_SSID; // your network SSID (name)
char PASS[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)

// To connect with SSL/TLS:
// 1) Change WiFiClient to WiFiSSLClient.
// 2) Change port value from 1883 to 8883.
// 3) Change broker value to a server with a known SSL/TLS root certificate
// flashed in the WiFi module.

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

const char broker[] = "192.168.1.209";
int port = 1883;
const char topic[] = "CumulusMX/Forecast";

char msg[20] = { 'W', 'e', 'e', 'r', 's', 'v', 'o', 'o', 'r', 'u','i', 't', 'z', 'i', 'c','h', 't', 'e', 'n', ': '};
int i = 0;

void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

// attempt to connect to WiFi network:
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(SSID);
while (WiFi.begin(SSID, PASS) != WL_CONNECTED) {
// failed, retry
Serial.print(".");
delay(5000);
}

Serial.println("You're connected to the network");
Serial.println();

// You can provide a unique client ID, if not set the library uses Arduino-millis()
// Each client must have a unique client ID
// mqttClient.setId("clientId");

// You can provide a username and password for authentication
// mqttClient.setUsernamePassword("username", "password");

Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);

if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());

while (1);

}

Serial.println("You're connected to the MQTT broker!");
Serial.println();

Serial.print("Subscribing to topic: ");
Serial.println(topic);
Serial.println();

// subscribe to a topic
mqttClient.subscribe(topic);

// topics can be unsubscribed using:
// mqttClient.unsubscribe(topic);

Serial.print("Waiting for messages on topic: ");
Serial.println(topic);
Serial.println();

// set up the LCD's number of columns and rows:
lcd.begin(16, 2);

}

void loop() {
// Print a message to the LCD.
lcd.setCursor(0,0);
int i = 0;
lcd.clear();
for (int i = 0; i <20 ; i++)
lcd.print(msg[i]);
delay (250);

char swaq = msg[0];
for (i =0; i < 20; i++)
msg[i] = msg[i+1];
msg[19] = swaq;

int messageSize = mqttClient.parseMessage();
if (messageSize) {
// we received a message, print out the topic and contents
Serial.print("Received a message with topic '");
Serial.print(mqttClient.messageTopic());
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");

// use the Stream interface to print the contents
while (mqttClient.available()) {
  Serial.print((char)mqttClient.read());

}
Serial.println();

Serial.println();

}
}

I look forward to the solution.
Greet,
Henk

This is where your message gets printed to the Serial Monitor so this is what you will need to change to make it also print to your LCD.

Take a few minutes and read this: How to get the best out of this forum

Then, go back and edit your post to include code tags around your code. It helps others help you

1 Like

An IoT (Internet of Things) weather station is a device that uses sensors to collect weather-related data such as temperature, humidity, air pressure, and rainfall. This data is then transmitted to a central server or cloud platform through the internet, where it can be accessed and analyzed. IoT weather stations can be used to monitor local weather conditions in real-time, providing valuable information for various applications such as agriculture, environmental monitoring, and home automation. By leveraging IoT technology, these weather stations can offer more accurate and timely data compared to traditional weather monitoring methods, enabling better decision-making and resource management.

Hello

Yes, this line is where the information lies. After all, the content of this rule - Serial.print((char)mqttClient.read()); - is displayed correctly.

But when I try to send this line to lcd.print, I can't get the right information on the LCD screen.

Sometimes the screen says -1-1-1-1-1. On the next attempt, all the blocks on the screen will go black one by one. I'm missing something essential.

One of many examples:

lcd.setCursor(16,1);

lcd.autoscroll();

lcd.print ((String)mqttClient.readString());

delay(200);

Other example:

lcd.setCursor(16,1);

lcd.autoscroll();

for (char i = 0; i <20 ; i++)

lcd.print((char)mqttClient.read());

delay(200);

I feel like I'm close to the solution, but I'm missing that one programming line.

The start of the second line is

lcd.setCursor(0,1);

If you are getting a -1, that is what is returned from .read() when there isn't a char available.

lcd.setCursor(0,1);
while (mqttClient.available()) {
  char c = mqttClient.read();
  Serial.print(c);
  lcd.print(c);
}

This does not take care of the fact that your message may be longer than the screen. You will have to figure out how you want to deal with that.

Yes, it works! This is the programming rule I needed: char c = mqttClient.read();
In the meantime I learned a few things more about programming. There are still small details: the text "The Weather" also scrolls across the screen, despite the line lcd.autoscroll(); comes later in the program.
And if the contents of mqttClient.read contain too many letters, the last letters will be moved to the top line. But that will be fine.
When I activate the Serial.print programming line, letters appear on the screen and serial monitor, but in random order and therefore not readable. This isn't a big deal, it's about the LCD screen.
With these lines, the content of the topic will appear on the bottom line of the LCD screen:
// use the Stream interface to print the contents
lcd.setCursor(0,0);
lcd.print ("The Weather: ");
lcd.setCursor(0,1);
lcd.autoscroll();
while (mqttClient.available()) {
//Serial.print((char)mqttClient.read());
char c = mqttClient.read();
lcd.print(c);
delay(200);

PS: I'm making a weather house. A male (bad weather on the way) or a female (good weather on the way) moves outside. This will be the next challenge: depending on the humidity (or barometric pressure or both), one figure will slide out or the other. This is done with the help of an encoder motor, controlled by the Arduino. I'll see how far I can get with programming.
Thank you and best regards,
Henk.

That is because your code is calling mqttClient.read() 2 times. Each time it is called it fetches a new character. That is why my example uses the variable c which is sent to both the Serial monitor and the lcd with only 1 read

Hello
I give up. After earlier advice on the forum, I get the right instruction to transfer the data from my weather station to LCD screen (16x2). However, the text of the weather station is too long for the screen: example: 18:01:00, 4.9C, 94%, Fine, becoming less settled.
I thought it was easy to make the text scroll on the bottom line. Nothing could be further from the truth. I can't do it. See my programming rules. I have checked many possibilities. In the example I'm sending, the top line also scrolls and the bottom line only gives dark blocks.
Who can help me to get lcd.print(c) to scroll correctly on the second line.

void loop() {

int messageSize = mqttClient.parseMessage();

if (messageSize) {
// we received a message, print out the topic and contents
Serial.print("Received a message with topic '");
Serial.print(mqttClient.messageTopic());
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");

// use the Stream interface to print the contents

 lcd.setCursor(0,0);
 lcd.print ("Weerbericht: ");
 lcd.setCursor(0,1);
while (mqttClient.available()) {
   char  c = mqttClient.read(); 
   Serial.print (c); 
   
} 

char c = mqttClient.read();
for (int positionCounter = 0; positionCounter < messageSize; positionCounter++) {
// scroll one position left:
lcd.scrollDisplayLeft();
lcd.print(c);
delay(150);
}
Serial.println();

Serial.println();

}

}

Thank you and best regards,

Henk

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