The LM335 and it’s serieresistor

The LM335 belongs to a range of a fairly accurate and simple to use temperature sensors.

The LM335 operates from -40°C to 100°C. It’s output is lineair with 10mV/°Kelvin (¶ 6.6 in the datasheet). It can be used in two ways: Calibrated and uncalibrated mode. The difference is a  10kΩ potentiometer that is used to regulate the output voltage to 2.98 Volt at 25°C (25°Celsius is 298.15°Kelvin) . With more and more devices running off of 3.3 Volt, the question is sometimes raised: will the LM335 run off of 3.3 Volt as well. Going through the datasheet you will not see a min or max value stated for the voltage to be used as all depends on the current through the LM335 and that current is determined by a series resistor (R1 in Fig. 1)

If we want to use the calibrated configuration of the LM335 then this is how to calculate the series resistor for the LM335:
According to the datasheet, the potentiometer needs to set the voltage over the LM335 at 2.98 Volts at  25°C (¶ 6.4 in the datasheet). The LM335 needs between 400uA and 5 mA (¶ 6.2 in the datasheet). Suppose that the max temperature we want to measure is 30 C (=303.15 °K). The output then will be 3.0315 Volt (let’s say 3.03 V).
At 3.03V the current through the 10k potentiometer will be 3.03/10k=303uA. The minimum current that needs to flow through the LM335 is 400uA, so R1 needs to supply 703uA over a voltage of Vcc-3.03V.

So at 5 Volt that would be 1.97/0.703 = 2.8kΩ
At 3.3 Volt it would be 0.27/0.703 = 0.384kOhm =384Ω
(Note 703uA= 0.703mA = 0.000703A. I chose to divide by mA so I get outcome in kΩ).
Now we still have to check if the current will not be too high at the lowest temperature we want to measure:
Let’s say our minimum temperature is 0°C that is 273.15. At 10mV/°K that means an output voltage of 2.73 Volt.
At 5 Volt the resistor current will be (5-2.73)/2.8kΩ = 810uA. We still need to subtract 2.73V/10kOhm=273uA which flows through the potentiometer so we have 810-273=537uA, which is well below the 5mA max.

If we calculate that for 3.3Volt, we find the following:
The resistor current will be (3.3-2.73)/384=1.5mA. Subtract 273uA that flows through the potentiometer and that gives roughly 1.23mA, well within limits.

If you want to measure temperatures higher than 30°C then R1 has to be smaller. When using 3.3 Volt the  theoretical maximum temperature measurable is 330°K which is about 57°C. In practice however that does not work as you need a drop voltage over R1 so the value of R1 cannot be zero, or, in other words: you cannot connect the LM335 directly to Vcc and still expect to get an output lower than Vcc.

Bet let’s see how that would be at 50°C (323.15°K) and 3.3V Vcc :
Well again you need 703uA but this time over 0.07V.
That gives a value  for R1 of 100Ω.
But then at 0 degrees the current is 5.7mA. Still need to subtract 2.73uA which gives 5.4mA which is out of spec.

A program would be as follows:

```//A0 is used to read the LM335
void setup()
{
Serial.begin(9600);
}
void loop()
{
float millivolts= (rawvoltage/1024.0) * 5000;
float kelvin= (millivolts/10);
Serial.print(kelvin);
Serial.println(" degrees Kelvin");

float celsius= kelvin - 273.15;
Serial.print(celsius);
Serial.println(" degrees Celsius");

float fahrenheit= ((celsius * 9)/5 +32);
Serial.print(fahrenheit);
Serial.println(" degrees Fahrenheit");

delay(2000);
}```

Beware though that the ESP8266, in spite of it being a 3V3 device only wants a maximum of 1 Volt on its ADC

The W5100 bug(s) – and how to fix it (them)

Bug 1- The SPI bug

On a recent project in which I shared the SPI bus of a 3V3 8MHz ProMini, with a W5100 Ethernet module and another SPI slave, I experienced some problems: sometimes it would work perfectly, sometimes not.
I had hooked up the ethernetmodule with Pin D10 as Chipselect and the other slave (an RFM69) with Pin D8 as Chipselect. Pretty standard and it should work, shouldnt it?
Well as it is, it didnt. Oddly enough, I had build it before with another Ethernet module and that worked fine.
When I connected my EthernetShield in the same way, the issue was gone. Time to throw suspicion on my Funduino W5100 Ethernetmodule. Well on inspection it is immediately clear that eventhough the functionality is supposed to be the same, the ethernetshield and also my previous module have more chips than my Funduino module. Why for instance does my shield have a 74LVC14 and my Funduino module just the W5100 chip and nothing more?

When looking at the circuit of the Ethernetshield it is clear that only one gate of the 74LVC14 (a SchmittTrigger inverter) is used: it takes the SS signal (the ‘chipselect’) inverts that and sends that inverted signal to Pin 31 of the W5100. Pin 31 is the SEN pin.

In the Funduino module that was different. The ‘SEN’ pin is just tied high to 3V3 with a 10k resistor. My shield has that pull-up resister as well, but still is controlled by the inverted chipselect signal.

Time for the datasheet of the W5100

Hmm.. that doesnt say much, other than that in my module the SPI mode is enabled, however, judging from the 74LVC14, it seems that this pin needs to be driven to LOW when the Chip is not selected. In other words, it is apparently necessary to disable the SPI mode in order to release the bus to another slave.

Time for some soldering: apart from the Vcc and ground, one needs two signals: the SS pin and the SEN pin. As the W5100 is an 80 LQTF chip, at my age (eyes) I was not even going to try soldering on the chip, but fortunately the Pullup resistor gives an entry point to the SEND signal and the connector is where we find the SS signal

I used a 74LCV14  (Low Voltage Inverting SchmittTrigger) for my modification, but I am sure an 74LC04 or 74LVT04 (an inverter) would do just as well. If you vcannot find the 74LCV14, try a 74LVT14 or 74HC(T)14 (it accepts  2 Volt Vcc). John Crouchley who also describes this problem uses a CMOS CD4011. He feeds that from 5Volt, which I did not want to do. It should be posible though, given the fact that the W5100 pins apear to be 5 V tolerant. Perhaps even a simple 1 transistor inverter is possible. Ideal would be an 74AHC1G04 as that is only a single inverter chip that measures only 2x3mm and can easily find a plce on the module.
Currently my modification is breadboarded. I will think of a neat solution and then add some more pictures.

Bug 2- The ‘510’ bug

There is another problem with some of the ‘asian webstore’ W5100 based Ethernet shields which isnt really a bug with the W5100 but more a problem with bad sourcing.
Some of those shields refuse to make contact with the internet because of some wrong components (resistors)In the picture here of the top of an ethernet shield, directly right of the Ethernet jack there is a “spider” resistor that is labelled with “49R9” that are actually 4 resistors in one  package with each a value of 49.9 Ohm. Apparently that was hrd to source at some time and  clone manufacturers decided to use 51 Ohm resitors. That is not a problem if indeed they had used 51 Ohm, but by mistake 510 ohm resistors were used (labelled ‘511’). Resistors with a value of 51 ohm should have been labelled with ‘510’.
So if you have such a board you need to replace the 510 ohm resistors. If you can’t find the proper replacement resistorpack then apparently it is also OK to solder  a 100 ohm resistor between pin 1-2 (Tx+/Tx-) and a 100 ohm resistor between pin 3 and 6 (Rx+/Rx-) as explained here. (So 2×100 Ohm resistors in total).

Bug 3 – The Funduino Reset Bug

The “Funduino” W5100 module as is a cheap, but qualitatively good W5100 board. However, apart from the ‘problem’ of not being able to share the SPI bus in unmodified state (adressed above), some  people have a lot of trouble getting it to work in the first place. The problem is then most likely in the Reset of the module. Modern versions of the Ethernetshield have a seperate Reset controller, that is triggered by the RST of the Arduino. The Funduino Module, just has its RESET tied to 3.3V via a 10 k resistor. As a result the Module’s reset state is a bit unpredictable. Some people get it to work by powering the module up and down a few times, but that remains random luck. What I found that works immediately is to add a slight delay in the setup, before the Ethernet connection is initialized. For me 250mS was enough, but you may need a bit more or a bit less.
So my Setup looks as follows:

```void setup() {
// setup ethernet communication using DHCP
delay(250);//```

Also, when you use the shield, the Reset pins of the Arduino and the shield are connected, so the Arduino can reset the shield. With this module you cannot do that: if you would connect both resets, you will notice that you cannot upload sketches. Perhaps it will work if you only connect the RST after you upload a sketch, I did not try that, too much hassle. I found the 250mS delay to work for me.
This ‘bug’ does not happen with all Funduino W5100 modules. Supposedly some batches are ‘OK’. There are 2 identification numbers: one on the PCB and one on the RJ45 jack. Supposedly if that says “15/10”  it is OK, “14/10” is not. Mine said “16/38” and needed the delay.
The only conenctions (other than Vcc and ground)  that I make are:
D10  -> nss
D11  -> miso
D12  -> mosi
D13  -> sck

Upload Data to Thingspeak through MQTT with an ESP8266

Sending  values to Thingspeak via the Thingspeak API is well known. There is another way as well: through MQTT. Thingspeak has recently (5 dec 2016) added a (one way) MQTT broker for this at `mqtt.thingspeak.com:1883`.

There are two topics one can use:
To upload more than 1 field in one session use:
`channels/<channelID/publish/<channelAPI>`

To upload an individual channel use:
`channels/<channelID>/publish/fields/field1/<channelAPI>` (just using field1 as example)

In the first case, the payload string is as follows:
`field1=<value1>&field2=<value2>&status=MQTTPUBLISH`

In the second case the payload string is just `<value1>`

In the program below I am using the PubSubClient from Knolleary. The “credentials.h” file is a file that defines my WiFi credentials, you can either create such a file yourself or just insert your wificredentials.

I am using an ESP8266 to make the connection but ofcourse it is also possible to use an Arduino with Ethernet connection when you make the proper changes  in this file in order to connect to Ethernet.

To avoid using again a DHT11 as an example, I show uploading variables by using micros() and a counter

```#include "PubSubClient.h" //Knolleary
#include  <ESP8266WiFi.h> //ESP8266WiFi.h
#include   <credentials.h> //This is a personal file containing web credentials

const char* ssid = WAN_SSID;// this constant is defined in my credentials file
const char* password = WAN_PW;// ditto
//char* topic="channels/<channelID/publish/<channelAPI>
char* topic = "channels/123456/publish/T8I9IO457BAJE386";
char* server = "mqtt.thingspeak.com";

WiFiClient wifiClient;
PubSubClient client(server, 1883, wifiClient);

void callback(char* topic, byte* payload, unsigned int length) {
// handle message arrived
}

void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

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

String clientName="ESP-Thingspeak";
Serial.print("Connecting to ");
Serial.print(server);
Serial.print(" as ");
Serial.println(clientName);

if (client.connect((char*) clientName.c_str())) {
Serial.println("Connected to MQTT broker");
Serial.print("Topic is: ");
Serial.println(topic);

if (client.publish(topic, "hello from ESP8266")) {
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}
}
else {
Serial.println("MQTT connect failed");
Serial.println("Will reset and try again...");
abort();
}
}

void loop() {
static int counter = 0;

if (client.connected()){

if (client.publish(topic, (char*) payload.c_str())) {
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}
}
++counter;
delay(20000);
}
```

The file is available for download here. Whether this is a better method than with the api remains to be seen.
Currently the connection time is limited because of the limited number of sockets on Thingspeak so it is ‘connect->upload->disconnect’. Thingspeak currently cannot be used as a ‘broker’. The traffic is one way only. If your client is already connected to an MQTT network on your own private or public broker, then this method cannot be used without ‘bridging’ the two ‘networks’

Adding an MCP23017 16 port IO expander to Arduino or Esp8266

I am not claiming that what I am describing here is earth shattering or trailblazing, because in fact it is very simple and no doubt has been done by many already. But sometimes what is simple for the one, is still a question mark for the other, so here is quick ‘how-to’ of adding 16 I/O ports to your microprocessor. This is especially handy when working with a chip like the ESP8266 that has only limited I/O
The MCP23017 is an I2C enabled 16 I/O port chip. That means that you only need 2 pins (yes with Vcc and ground it makes 4) to control the chip and the added advantage is that you can share I2C with various other devices as well.

The 16 I/O lines are divided into an 8 I/O PORT A and an 8 I/O PORT B. Both can be used as input as well as output. The chip also has 2 configurable interrupts (that I will not be using). The physical layout of the chip makes it quite easy to use it on a piece of strip board.

The circuit (at right) is rather simple. At a last moment I decided to leave out the pull up resistors so it would be more flexible to use together with other I/O devices. The 3 Address pins A0-A2 determine the I2C address that ranges from 0x20 (all pins on ground) to 0x27 (all pins on Vcc).
The chip  can take a Vcc from 2.7V to 5V and this is perfect for 3.3 Volt devices as  the modern arduino’s and the ESP8266 range.

Using the chip in a program is fairly easy. There are good libraries available, but it might help if you know how to program the chip without a library.
In my case I have all  address lines tied to ground and therefore my I2C address is 0x20. Suppose I want to use all PORT A lines as outputs. I do that  as follows:

```Wire.beginTransmission(0x20);
Wire.write(0x00); // IODIRA register
Wire.write(0x00); // set entire PORT A to output
Wire.endTransmission();```

For PORT B that  is rather similar:

```Wire.beginTransmission(0x20);
Wire.write(0x01); // IODIRB register
Wire.write(0x00); // set entire PORT B to output
Wire.endTransmission();```

If we then want to send a specific value ‘X’ to that PORT A, we do that as follows

```Wire.beginTransmission(0x20);
Wire.write(0x12); // address port A
Wire.write(X);  // value to send
Wire.endTransmission();```

‘X’ ofcourse is a byte value that determines whether we set a specific port HIGH or LOW.
If for instance ‘X’is ‘0’ that means we write a LOW to all PORT A outputs. If it is 255 that means we write a HIGH to all PORT A outputs.
To determine what value to send, consider the 8 I/O lines of PORT A as a byte in which the individual bits determine HIGH or LOW.
So if we only want to make PORTA.0 HIGH and the rest LOW, we write a binary value of 0b00000001 =1 to the A register. If we want to make PORTA.0 and PORTA.2 HIGH and the rest LOW we write a binary value of 0b00000101 = 5.
For PORT B it is similar:

```Wire.beginTransmission(0x20);
Wire.write(0x13); // address PORT B
Wire.write(X);  // value to send
Wire.endTransmission();```

If we want to use PORT B (or PORT A for that matter) as input, we do that as follows:

```Wire.beginTransmission(0x20);
Wire.write(0x13); // address PORT B
Wire.endTransmission();
Wire.requestFrom(0x20, 1); // request one byte of data
byte input=Wire.read(); // store incoming byte into "input"```

The byte “input” will vary between 0 and 255, in which the individual bits determine the input on the corresponding IO line. So if ‘input’  reads ‘3’  which in binary is 0b00000011, that means that both IO line 0 and 1  were HIGH and the rest LOW

```#include <Wire.h> // Wire.h
byte input=0;
void setup()
{
Serial.begin(9600);
Wire.begin(); // wake up I2C bus
Wire.beginTransmission(0x20);
Wire.write(0x00); // IODIRA register
Wire.write(0x00); // set entire PORT A as output
Wire.endTransmission();
}

void loop()
{
// read the inputs of bank B
Wire.beginTransmission(0x20);
Wire.write(0x13);
Wire.endTransmission();
Wire.requestFrom(0x20, 1);

// now send the input data to bank A
Wire.beginTransmission(0x20);
Wire.write(0x12); // address PORT A
Wire.write(input);    // PORT A
Wire.endTransmission();
delay(100); // for debounce
}```

That’s basically it if you want to do the adressing yourself. Using a library, such as the one from Adafruit, makes it much easier though as it has commands to write and read from individual IO lines. One of the example programs to read a single button, looks  for instance like this:

```#include <Wire.h> // Wire.h

// Basic pin reading and pullup test for the MCP23017 I/O expander
// public domain!
// Connect pin #12 of the expander to Analog 5 (i2c clock)
// Connect pin #13 of the expander to Analog 4 (i2c data)
// Connect pins #15, 16 and 17 of the expander to ground (address selection)
// Connect pin #9 of the expander to 5V (power)
// Connect pin #10 of the expander to ground (common ground)
// Connect pin #18 through a ~10kohm resistor to 5V (reset pin, active low)
// Input #0 is on pin 21 so connect a button or switch from there to ground

void setup()
{
mcp.begin();      // use default address 0
mcp.pinMode(0, INPUT);
mcp.pullUp(0, HIGH);  // turn on a 100K pullup internally
pinMode(13, OUTPUT);  // use the p13 LED as debugging
}

void loop() {
// The LED will 'echo' the button
}```

Calculating Sunrise and Sunset on Arduino (or other microcontroller)

Knowing the hours of sunset and sunrise may be handy in a variety of situations, an automated chicken coop door might be only one example.

There are several ways to get the proper times: a lookup table in EEPROM, the Timelord library or one of its successors, the Dusk2Dawn library, a rather complicated calculation including the Julian calender, or a fairly simple approximation that I will discuss here.

This method uses the average of the earliest and latest sunset and then for any given day  adds or subtracts a certain amount of time with a maximum of half  of the difference between the earliest and latest sunrise.

Rob Tillaert discusses the method here. It presumes that the sunrise time follows a (co)sinoidal function. I will try to visualize it with a simple example:

Say that on June 23 the earliest sunrise of the year occurs at 4am, and that the latest sunrise of the year occurs at 23 December at 6 am.

Then you know that on any other day the sunrise is between 4 and 6 am. If you take the average that is 5 am, then you know that every other sunrise that year is either 0-1 hr later than 5 am or 0-1 hr earlier than 5 am.

It is the latter that is captured in the formula:

t=avg+0.5Δ*cos((doy+8)/58.09)

• avg is average sunrise time, in minutes since midnight
• Δ the difference between the earliest and latest sunrise time
• doy is the day of the year
• the 8 is there because we start on the wintersolstice: 23 December is 8 days before jan 1
• 58.09 is 365/2π. That is necessary because the cosinusfunction has max 2π as input.

If you live in a DST zone, the earliest sunrise wil be under DST, however you need the non-DST corrected time: the sun knows no DST. Calculate firstm then add DST later

For my location the earliest and latest sunrise are:

earliest sunrise is at 4.19 am
latest sunrise is at 8.51
in order to use them in our equation, we have to calculate them in minutes past midnight:
4.19= 4×60+19=259
8.51= 8*60+51=531
The average is (259+531)/2=395
the difference or delta is 531-259=272. We need half of that which is 137.
The equation then becomes:

395+137*cos((doy+8)/58.09)

To check the accuracy of the approximation, I plotted the actual sunrise times (blue curve) against the calculated sunrise time (red curve).

As it shows, the first half of the year is a perfect fit, the second half of the year seems to follow a more linear curve with the max deviation being 20 minutes, that may or may not be accurate enough for your project. With the aid of this curve though I could opt for a linear approximation for the 2nd half of the year.

For sunset we can practically use the same formula, be it that we now have to subtract the variable part rather than add it.
For my location the sunset is as follows:
latest: 22:07 =1327
Earliest: 16:27= 987
avg=2287/2=1144
delta=240 ->170
sunset=1144-170*cos((doy+8)/58.09)

That gives the following graph:

This time I didnt bother to enter all the  real sunset times, but it is clearly visible that there is a reasonable fit that could maybe be enhanced a bit by shifting it slightly more to left or decreasing the delta a bit. Again Red graph is the calculated sunset, the blue is the actual sunset. None of the graphs has been corrected for DST.

A procedure for the Arduino would look as follows:
Where DST is a byte indicating whether DST is active (1)  or not active (0).
The day of the year I pull from my RTC library but it can also be calculated as follows:
int(((month-1)*30.5)+dayOfMonth)

The sunrise and sunset are both given in minutes after midnight. The hour and minutes of the sunrise (and sunset) can be calculated by:
hour=sunrise/60
minute=sunrise%60

MQTT with the W5100 Ethernetshield

In a previous post I discussed the use of an old ENC28J60 ethernetshield for an MQTT node. The biggest setback of the ENC28J60 shield is that it uses a lot of memory. When using the newer W5100 Ethernetshield, there is a bit more room to play with. So here is a simple framework  for an MQTT node that doesnt’t only publish, but also reacts to simple commands that come in with a subscription.

```/*
Arduino UNO with W5100 Ethernetshield or  W5100 Ethernet module, used as MQTT client
It will connect over Wifi to the MQTT broker and controls a digital output (LED, relay)
and gives the Temperature and Humidity, as well as the state of some switches
The topics have the format "home/br/sb" for southbound messages and  "home/nb" for northbound messages
Southbound are messages going to the client, northbound are messages coming from the client
As the available memory of a UNO  with Ethernetcard is limited, I have kept the topics short
Also, the payloads  are kept short
The Northbound topics are
home/br/nb/temp  for temperature
home/br/nb/humid  for humidity
home/br/nb/deur  for a door switch
home/br/nb/l for  the lightintensity
home/br/nb/pr  for the status of a PIR sensor
home/br/nb/ip showing the IP number of the client
home/br/nb/relay showing the relaystate

There is only one southbound topic:
home/br/sb
The payload here determines the action:
0 -Switch the relay off
1-Switch the  relay on
2-Publish the IP number of the client
3 Ask for the relaystate REMOVED

On Startup, the Client publishes the IP number

*/
#include "Ethernet.h"
#include "PubSubClient.h"
#include "DHT.h"
//kennelijk  geeft update van DHT sensor library boven 1.2.1 een fout
#define CLIENT_ID       "Hal"
//#define TOPIC           "temp"
#define PUBLISH_DELAY   3000
#define DHTPIN          3
#define DHTTYPE         DHT11
#define ledPin 13
#define relayPin 8
String ip = "";
bool statusKD = HIGH;
bool statusBD = HIGH;
bool statusGD = HIGH;
bool relaystate = LOW;
bool pir = LOW;
bool startsend = HIGH;
int lichtstatus;
uint8_t mac[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x06};

EthernetClient ethClient;
PubSubClient mqttClient;
DHT dht(DHTPIN, DHTTYPE);

long previousMillis;

void setup() {
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(relayPin, OUTPUT);

// setup serial communication

Serial.begin(9600);
while (!Serial) {};
Serial.println(F("MQTT Arduino Demo"));
Serial.println();

// setup ethernet communication using DHCP
if (Ethernet.begin(mac) == 0) {
//Serial.println(F("Unable to configure Ethernet using DHCP"));
for (;;);
}

Serial.println(F("Ethernet configured via DHCP"));
Serial.println(Ethernet.localIP());
Serial.println();
/*
Serial.println(Ethernet.localIP()[0]);
Serial.println(Ethernet.localIP()[1]);
Serial.println(Ethernet.localIP()[2]);
Serial.println(Ethernet.localIP()[3]);
*/
ip = String (Ethernet.localIP()[0]);
ip = ip + ".";
ip = ip + String (Ethernet.localIP()[1]);
ip = ip + ".";
ip = ip + String (Ethernet.localIP()[2]);
ip = ip + ".";
ip = ip + String (Ethernet.localIP()[3]);
//Serial.println(ip);

// setup mqtt client
mqttClient.setClient(ethClient);
//mqttClient.setServer(mqttServer, 1883);
// mqttClient.setServer("test.mosquitto.org", 1883);
//  mqttClient.setServer( "raspberrypi.local",1883);
mqttClient.setServer( "192.168.1.102", 1883);
//Serial.println(F("MQTT client configured"));
mqttClient.setCallback(callback);
// setup DHT sensor
dht.begin();
Serial.println(F("DHT sensor initialized"));

Serial.println();
Serial.println(F("Ready to send data"));
previousMillis = millis();
mqttClient.publish("home/br/nb/ip", ip.c_str());
}

void loop() {

statusBD = digitalRead(4);// FrontdoorSwitch
statusGD = digitalRead(5);// Garagedoor Switch
statusKD = (digitalRead(6));//LivingRoom Switch

relaystate = digitalRead(relayPin);// Reads the state of a relay

// it's time to send new data?
if (millis() - previousMillis > PUBLISH_DELAY) {
sendData();
previousMillis = millis();

}

mqttClient.loop();
}

void sendData() {

char msgBuffer[20];
float h = dht.readHumidity();
float t = dht.readTemperature();
Serial.print("Temperature: ");
Serial.print(t);
Serial.println("oC");
Serial.print("Humidity: ");
Serial.print(h);
Serial.println("%");
Serial.print("Relay is: ");
Serial.println((relaystate == LOW) ? "OPEN" : "CLOSED");
if (mqttClient.connect(CLIENT_ID)) {
mqttClient.publish("home/br/nb/temp", dtostrf(t, 6, 2, msgBuffer));
mqttClient.publish("home/br/nb/humid", dtostrf(h, 6, 2, msgBuffer));
mqttClient.publish("home/br/nb/deur", (statusBD == HIGH) ? "OPEN" : "CLOSED");
mqttClient.publish("home/br/nb/garage", (statusGD == HIGH) ? "OPEN" : "DICHT");
mqttClient.publish("home/br/nb/bel", (statusKD == HIGH) ? "OPEN" : "CLOSED");
mqttClient.publish("home/br/nb/l", dtostrf(lichtstatus, 4, 0, msgBuffer));
mqttClient.publish("home/br/nb/p", (pir == HIGH) ? "OPEN" : "CLOSED");
mqttClient.publish("home/br/nb/relay", (relaystate == LOW) ? "OPEN" : "CLOSED");
mqttClient.subscribe("home/br/sb");
if (startsend) {
// mqttClient.publish("home/br/nb/relay", (relaystate == LOW) ? "OPEN" : "CLOSED");
mqttClient.publish("home/br/nb/ip", ip.c_str());
startsend = LOW;
}
}
}

void callback(char* topic, byte* payload, unsigned int length) {
char msgBuffer[20];
// I am only using one ascii character as command, so do not need to take an entire word as payload
// However, if you want to send full word commands, uncomment the next line and use for string comparison
//payload[length] = '\0';            // terminate string with '0'
//String strPayload = String((char*)payload);  // convert to string
// Serial.println(strPayload); //can use this if using longer southbound topics
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");//MQTT_BROKER
for (int i = 0; i < length; i++) {
}
Serial.println();

// Examine only the first character of the message
if (payload[0] == 49)             // Message "1" in ASCII (turn output ON)
{
digitalWrite(LED_BUILTIN, HIGH);    //
digitalWrite(relayPin, HIGH);
} else if (payload[0] == 48)      // Message "0" in ASCII (turn output OFF)
{
digitalWrite(relayPin, LOW);     //
digitalWrite(LED_BUILTIN, LOW);
} else if (payload[0] == 50)
{
mqttClient.publish("home/br/nb/ip", ip.c_str());// publish IP nr
} else {
Serial.println("Unknown value");
mqttClient.publish("home/br/nb", "Syntax Error");
}

}
```

You will find the full code for download here.

Setting up a local MQTT broker on the Raspberry Pi

On the web there are a ton of instructions and how to’s on how to do this, but I found  it easiest to just  issue two commands on Raspian Jessie:
```sudo apt-get update sudo apt-get install mosquitto mosquitto-clients python-mosquitto```

then to test if it was all working, I opened 2 ssh terminals to my raspberry with:
`ssh pi@192.168.1.102`  (the latter being the ip nr from my raspberry)
and then in one of those terminals I entered:
`mosquitto_sub -d -t hello/world`
this made the terminal I will call Terminal 1 subscribe to the topic “hello/world”
in the other ssh terminal window (Terminal 2) I entered
`mosquitto_pub -d -t hello/world -m "Greetings from Terminal2"`
and immediately I got that message published in Terminal 1
(actually you don’t need the ‘-d’ option. That is just for diagnostics)
So I knew my local Mosquitto broker was working, at least within one machine, the raspberry on which it was installed. Time to check if it also worked on other machines. To do that I opened a third terminal on my desktop that didnt ssh to the raspberry but just gave a command line to the machine I was working on (a regular Linux desktop).

Before I could have that machine subscribe to an MQTT topic, I first had to install the MQTT client with:
`sudo apt-get install mosquitto-clients`

when that was done I entered:
`mosquitto_sub -h 192.168.1.102 -t hello/world`

Now when I published a message on terminal2 (thats the raspberry) it got published on terminal1 (that same raspberry) and on terminal3 (a regular desktop), so now I knew everything was hunky dory.
However, having to use terminal command lines to check your MQTT broker is not the most convenient. I can advise everybody who works with MQTT to install MQTT-spy. That is a jar file that basically is a publisher and a client that keeps track of MQTT messages on your network.

It comes pre-configured with 3 public brokers but adding your local broker is very simple:
After starting MQTT-spy go to  ‘Connections-New Connection” Fill out a name for your connection and under the ‘connectivity tab’ add (in my case): 192.168.1.102:1883  with 1883 being the  standard MQTT port.
Then go to the ‘other’tab and check ‘auto subscribe when opened’.
Now in the main window add a subscription tab called ‘hello/world’ and republish  the message from Terminal2: it should appear in the receive window of mqtt-spy. Vice versa, if  you publish a message from within mqtt spy, it will appear on terminal 1 also