MQTT with the ENC28J60 Ethershield

My old ENC28J60 based shield surely has gathered some dust
My old ENC28J60 based shield surely has gathered some dust

While playing with MQTT on various ESP8266’s, I started to wonder if maybe I could do something with an old ENC28j60 shield and module I still had laying around and actually hardly ever used.

For the youngsters: The ENC28J60 Ethernetshield was the first shield to connect the Arduino with the internet. The major drawback of the chip was that it was lacking a stack, that subsequently had to be constructed in software. As a result it was kinda memory hungry. The initial version was without an SD card slot, the later version had an SD card slot. There were two libraries available: The Ethercard and the Ethershield library. The UIPEthernet library came later.
As far as I could figure out, the PubSubClient library that is needed for MQTT doesnt work with the original Ethershield/EtherCard libraries. It does work with the UIPEthernet library though (extended fork here). The UIPEthernet library is a smart piece of coding that made programs written for the W5100 Ethernetshield suitable to be used with the ENC28J60 Shield, simply by changing the included library. Ofcourse there is a price to pay for this, namely more memory consumption. There is also an MQTT client for the ENC28J60/Atmega328 based Nanode.

Anyway, there still is enough memory to read a DHT11 sensor an analog port and some switches. In my case those were 3 door contacts. The PubSubClient is the original from Knolleary, though normally I am more a fan of the fork by Imroy. For this example I have used the Mosquitto public broker but ofcourse any broker can be used. I have installed the Mosquitto broker on a local raspberry and I found that a call to (“raspberrypi.local”,1883) does not work, using the  local ip number does work though

MQTT-Output ‘Dicht’ means ‘Closed’

The program is rather ‘spartan’, to save space. Print statements have been removed or commented out after initial testing.

#include <UIPEthernet.h>
#include "PubSubClient.h"
#include "DHT.h"

#define CLIENT_ID       "UnoMQTT"
#define INTERVAL        3000 // 3 sec delay between publishing
#define DHTPIN          3
#define DHTTYPE         DHT11
bool statusKD=HIGH;//living room door
bool statusBD=HIGH;//front door
bool statusGD=HIGH;//garage door
int lichtstatus;
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};

EthernetClient ethClient;
PubSubClient mqttClient;

long previousMillis;

void setup() {
  // setup serial communication
  // setup ethernet communication using DHCP
  if(Ethernet.begin(mac) == 0) {
    //Serial.println(F("Ethernet configuration using DHCP failed"));
  // setup mqtt client
  //mqttClient.setServer("",1883); //for using local broker
  //Serial.println(F("MQTT client configured"));

  // setup DHT sensor
  previousMillis = millis();

void loop() {
  lichtstatus = analogRead(A0);
  // check interval
  if(millis() - previousMillis > INTERVAL) {
    previousMillis = millis();

void sendData() {
  char msgBuffer[20];
  float h=dht.readHumidity();
  float t = dht.readTemperature();
  if(mqttClient.connect(CLIENT_ID)) {
   mqttClient.publish("hal/temp", dtostrf(t, 6, 2, msgBuffer));
   mqttClient.publish("hal/humid", dtostrf(h, 6, 2, msgBuffer));
   mqttClient.publish("hal/door", (statusBD == HIGH) ? "OPEN" : "DICHT");
   mqttClient.publish("hal/garage",(statusGD == HIGH) ? "OPEN" : "DICHT");
   mqttClient.publish("hal/kamer",(statusKD == HIGH) ? "OPEN" : "DICHT");
   mqttClient.publish("hal/licht", dtostrf(lichtstatus, 4, 0, msgBuffer));
 //hal=hallway, DICHT=Closed, kamer=room, licht=light
The old ENC28J60 shield at work
The old ENC28J60 shield at work

Just for completeness sake, this sketch takes about 77% of memory. This same sketch for the WIZ5100 based Ethernet shield, with the  Ethernet.h library takes about 52% of memory. If you decide to adapt the sketch, be careful with altering the character strings. For instance, using the string “OPEN” 3 times is likely less memory consuming than having 3 different strings of the same or even shorter length. Obviously the ‘topic’ strings take a lot of space as well and if you were to shorten them to less meaningful names, you could add more sensors such as for instance a PIR sensor.

Should you copy the program from this  blog page, you may copy ‘stray characters’  that you have to delete. You can also download it here.

A final warning… after I updated my libraries, including the Adafruit DHT library, I received an error on compiling this sketch. That disappeared when I returned it to version 1.2.1. I thought I was not using the Adafruit library but the Tillaert library, but DHT libraries come a dime a dozen so maybe my compiler linked in another than I thought.
(The sketch is my adaptation of work i found on internet, but I think the original source is from Luca Dentella)

Reset a program from a ‘freeze’

While doing a test run on software for an incubator the software did fine, until suddenly on the ninth day weird things started to happen: the LCD showed some odd data and in spite of a low temperature the heating had not kicked in. I resetted the software, wondering what it could be but only an hour later again something off happened. This time in spite of the temperature being well over the upper limit, the heating was not switched off.
I checked my code, which really wasn’t so complicated: Read DSB1820, read DHT11, compare with high and low limit, switch a pin on or off and write the value to an LCD and I couldn’t find a single mistake and don’t forget, it had run flawlessly for 9 days. I suspected my display. This was a 20×4 LCD with I2C module with 4k7 pull up. Nevertheless there might still have been some ‘static’ on the SDA and SCL lines that supposedly can cause the Arduino to freeze.

Obviously that is not good if you are running an incubator as you dont want to check it and find your eggs boiled.
So, other than maybe straightening out the LCD cables a bit, I decided that I needed some software protection against ‘freezes’
The only (and possibly best) way to do this is with the watchdog timer. I dont want to go into the specifics and the background of the watchdog timer, but just keep it on a practical level.
What we do is to set-up the watchdog timer to initiate a system reset after say 4 seconds. Then in our loop we do a reset of the watchdog timer so it starts counting from zero again. So as long as the program tells the watchdog timer “I am still running” nothing will happen. Should the program freeze up, it will not reset the watchdog timer and then after 4 seconds the watchdog timer will reset the entire system.
It is very well possible to use the watchdog timer by manipulating the various registers yourself, but it is much simpler to use the watchdog libary that is part of the avr libraries.
We do this as follows:

#include <avr/wdt.h>

void setup()
	//wdt_enable(WDTO_1S);// 1 sec
	wdt_enable(WDTO_2S);// 2 sec
	//wdt_enable(WDTO_4S);// 4 sec
	//wdt_enable(WDTO_8S);// 8 sec

void loop()
	//  your program

1 Wire LCD interface: Part 1

The one wire LCD interface has been around on the internet for some time already and made popular by Roman Black, although he claims he is not the inventor of the principle. His article is mainly PIC processor oriented, but it gives a good explanation of the principle. Myke Predko is also a name that  should not be unmentioned as pioneer in 1 wire LCD driving. Also this article about  one wire driving of a shift register is very informative

The ShiftRegLCD123 website from Raron used to give a lot of information as well, along with circuits, but that (the Wiki) seems to have disappeared. But his library is in codebender.

In brief, the One Wire interface uses a latched shift register in which the clock and the latch are taken from the data signal through two RC networks that produce the necessary delay. Circuits are a plenty on the interweb, but finding the proper driver for it can be confusing sometimes.

Although the interface on the data, clock and latch lines is rather standard, the connection between the shift register and the LCD has thre major variants that for now i will just call the Roman Black, the LCD3Wire circuit (yes, it is 1 wire) and the ShiftRegLCD123 circuit. Also Elektor has published a 1 wire interface (Detlef Hanemann)(Published in issue 9/2015 on page 92) with yet again a different shift register to LCD connection. Their setup is said to have several advantages over the setup used by Roman Black, it uses the Q7′ direct output of the shift register to trigger the output latch register to carry over automatically the shifted data to the output pins. But for that it requires a monoflop built around a BS170 FET to generate the E-pulse. The setup to be used in Francisco Malpartida’s LCD library is yet again different from the other 3 and uses a diode to create an AND gate

Roman Black






Malpartida LCD library

. Roman Black LCD3Wire Shiftreglcd Elektuur Malpartida
RS  Qc  Qb  Qc  Qg  Qg
E  Qd  Qd  Qh  Qh’  Qh’ sort of
D4  Qe  Qh  Qd  Qa  Qe
D5  Qf  Qg  Qe  Qb  Qd
D6  Qg  Qf  Qf  Qc  Qc
D7  Qh  Qe  Qg  Qd  Qb

Driving these OneWireLCD’s thus differs per configuration. The ShiftRegLCD123 library can do both the ShiftRegLCD and the LCD3Wire protocol. The Liquid Crystal Library of Francisco Malpartida  does have a One Wire protocol but make sure you have the latest version. However, it relies on connections different from the others mentioned:
// Bit #0 (QA) – not used
// Bit #1 (QB) – connects to LCD data input D7
// Bit #2 (QC) – connects to LCD data input D6
// Bit #3 (QD) – connects to LCD data input D5
// Bit #4 (QE) – connects to LCD data input D4
// Bit #5 (QF) – optional backlight control
// Bit #6 (QG) – connects to RS (Register Select) on the LCD
// Bit #7 (QH) – used for /CLR on the HW_CLEAR version (cannot be changed)
// (Q’H) – used for Latch/EN (via the diode AND “gate”) (cannot be changed)

// -----------------------------------------------
//                         74HC595     (VCC)
//                       +----u----+     |          2.2nF
// (LCD D7)------------1-|QB    VCC|-16--+      +----||----(GND)
// (LCD D6)------------2-|QC     QA|-15         |
// (LCD D5)------------3-|QD    SER|-14---------+--[ Resistor ]--+
// (LCD D4)------------4-|QE    /OE|-13--(GND)         1.5k      |
// (BL Circuit)--------5-|QF    RCK|-12---------+                |
//                       |         |             \               |
// (LCD RS)------------6-|QG    SCK|-11-----------)--------------+--(Seri
//                     7-|QH   /CLR|-10--(VCC)   /               |
//                  +--8-|GND   Q'H|--9---|<|---+--[ Resistor ]--+
//                  |    +---------+     diode  |      1.5k
//                  |                           |
//                  |      0.1uF                |
//                (GND)-----||----(VCC)         +----||----(GND)
//                                              |   2.2nF
// (LCD EN)-------------------------------------+
// (LCD RW)--(GND)

The Elektuur/Elektor configuration has its own program, or here (both direct download link)

A capacitive soil humidity sensor: Part 3

Initially I imagined the probe as a sleek device with a wire coming out that one would stick in the soil, if necessary completely. This would mean that the circuit pcb would be an integral part of the PCB that  formed the plates, but as always, things go different in practice. For one thing , the piece of PCB I intended to use just wasnt long enough. Second, my PCB etching possibilites are temporarily impeded. Third, I wanted to add an LDR, meaning that I had to have some sort of  translucent cover.

I constructed the circuit on a small piece of stripboard:

IMG_20160225_163125 i2cprobe

With regard to the LDR, sure that is nonsense. If I want to add an LDR I  could just as well add it to my base station. But I am not adding it because I have to, I am adding it because I can and because I wanted to get some experience in programming an I2C slave. An LDR might not be so usefull but in future I may want another sensor, e.g.a sensor that reads if there is really water flowing from the irrigation tube.

Also I had decided on putting the capacitor plates back to back, but as I did not have double sided PCB I just used two pieces glued and  soldered(!) together.
So My BOM was rather simple:

  • 2 equal size pieces of PCB  Size depends on what you have, but do not make them too small. I used 12×3 cm.
  • 1 piece of 0.5-1.0 cm plastic for a baseboard. I used an old cutting board.
  • 1 clear/translucent cover, I used the lid of a whipped cream spray can.
  • 1 piece of  thin 4 wire cable, length depending on your need

pcbprobe2I glued the two piecesof pcb back to back. drilled a hole in all 4 corners and through soldered a piece of wire through each hole, thus anchoring the plates together. I removed some copper around the solder so it would become an island isolated from the rest of the plate. (See picture).

Soldering the plates together in the corners may not be necessary if you decide to electrically isolate them from the soil with e.g. shrink tube.

Eventually I will place an NTC on the plate as well after it is covered with Shrink tube. Esthetically it might be better to put the NTC under the shrink tube, but that could create an air pocket.


baseplateI made the base plate from a o.5 cm thick piece of soft plastic. Cut out a round shape  with a 5.5 cm diameter to fit the base of my  clear dome and  made a slit 3 x0.3 cm into that in which the PCB  fits snug. made a round hole for the connecting cable.




I soldered two wires on the top of the PCB, one on each side. Soldered wires on an NTC, insulated those, attached the NTC to the bottom of the PCB with the wires leading to the top and then covered the PCB with shrink wrap.

probeEventually the probe looks like this (picture)probe3


A capacitive soil humidity sensor: Part 2

capacitive74HC14_attinyIn a previous article I presented a simple way to read a capacitive moisture sensor with a simple RC generator.
In this post I will present a sensor with some added functionality that can be read through I2C. The circuit (figure) doesnt need much explanation: the RC generator we saw in the previous article and the two variable resistors in a voltage divide read by analogue inputs. The Attiny 45 (NOTE, it is NOT an Attiny25) is the heart, or rather the brains of the sensor. As the Attiny  functions as an I2C slave we will need the TinyWireS library. The library comes with some examples and one example was quite easy to rework to what I needed. The code is as follows.

#define I2C_SLAVE_ADDRES 0x4
#include <TinyWireS.h>//
#define TWI_RX_BUFFER_SIZE ( 16 )

volatile uint8_t i2c_regs[] =
// Tracks the current register pointer position
volatile byte reg_position;
const byte reg_size = sizeof(i2c_regs);

byte LDRvalue;
byte NTCvalue;
int MoistPulse;

 * This is called for each read request we receive, never put more than one byte of data (with TinyWireS.send) to the
 * send-buffer when using this callback
void requestEvent()
	// Increment the reg position on each read, and loop back to zero
	if (reg_position >= reg_size)
		reg_position = 0;

 * The I2C data received -handler
 * This needs to complete before the next incoming transaction (start, data, restart/stop) on the bus does
 * so be quick, set flags for long running tasks to be called from the mainloop instead of running them directly,
void receiveEvent(uint8_t howMany)
	if (howMany < 1) { // Sanity-check return; } if (howMany > TWI_RX_BUFFER_SIZE)
		// Also insane number

	reg_position = TinyWireS.receive();
	if (!howMany)
		// This write was only to set the buffer for next read
		i2c_regs[reg_position] = TinyWireS.receive();
		if (reg_position >= reg_size)
			reg_position = 0;

void setup()
	pinMode(1, INPUT);

void loop()
	 * This is the only way we can detect stop condition (
	 * it needs to be called in a very tight loop in order not to miss any (REMINDER: Do *not* use delay() anywhere, use tws_delay() instead).
	 * It will call the function registered via TinyWireS.onReceive(); if there is data in the buffer on stop.

void readSensors()
	LDRvalue = (analogRead(A2)) >>2; // max value is 1023/4=255 is 1 byte (FF) physical pin3=PB4=A2
        i2c_regs[0] = LDRvalue;
	NTCvalue = (analogRead(A3)) >>2; // max value is 1023/4=255 is 1 byte (FF) pin2=PB3=A3
	i2c_regs[1] = NTCvalue;
	//pulsepin= pin6=PB1
	MoistPulse = pulseIn(1, HIGH);
	i2c_regs[2] = highByte(MoistPulse); // or use = MoistPulse >> 8;
	i2c_regs[3] = lowByte(MoistPulse); // or use = MoistPulse & 0xFF;

I have called the pulseIn function with an integer rather than with a long. This means that you will have to choose a value for R3 that gives a reasonable range for the type of soil that you use. A range of say 0-200 uS is very reasonable. Once you have done that you can also add a timeout to the pulseIn function. This should be abt 2 times the pulselength you expect (but depends on the duty cycle). With regard to the two variable resistors, they are in pull up so their value is Rntc = Rseries/((1023/ADC) – 1));  For the NTC this could be substituted in a Steinhart Hart approximation

The code to call the values (and that is loaded onto the master arduino) is even simpler:

#include <Wire.h>
void setup() {
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output

void loop() {
  for (byte i=0;i<4;++i){
  Serial.println(readRegister(i),HEX); // print the character
Serial.println(" ");

uint8_t readRegister(uint8_t regaddress)
	Wire.requestFrom(4, 1);


This code only prints out the values, you still need to combine the LSB and MSB from the cycle time and e.g. switch a pump based on the value. You could do that with this function:

int combine (byte lsbv, byte msbv)
	int value = msbv << 8;
	value = value | lsbv;
	//value= msbv<<8 | lsvb;//if you want to do it in one go
	return value;

Don’ t forget that the I2C lines need pull-up resistors of 4.7-10k.

In a next article I will present the construction of the probe itself.

A capacitive soil humidity sensor: Part 1

An automated plant/garden watering system is a popular application for  the Arduino and other microcontrollers. The humidity sensor that is often used is  often a resistance meter: 2 probes in the soil form a resistor and as part of a voltage divider that gives info on the amount of water in the soil.
The major shortcoming of these sensors is that since there is a current flowing, the probe is sensitive to electrolytic corrosion. Another shortcoming is that it doesnt really give information on the soil humidity, but more on the  ion concentration in the soil. Remember: pure water is a bad conductor, It are the ions in the water that make it a conductor.

To get around the corrosion, people have started to feed the probe with AC rather than DC current, but at best the circuits for this supply a pulsating DC current. Another  possibility to minimize corrosion is to  switch off  the current to the probe and only switch it on when a measurement is taken, say every 5  minutes.

All these measures help but even then, just due to the contact with moist soil, the metal on the probe will corrode and weather.
Another method is to encase the probes in plaster. Some people swear by it but I  think it is bothersome. Also the plaster encased probe has a lag as it will retain water  for some time after the  soil is already dry and it will still be dry for some time after the soil is already moist.

Capacitive measuring is a way to avoid these problems. With capacitive measurement the ‘plates’ of the capacitor can be electrically isolated from the soil and the soil in fact forms the dielectrum of the capacitor. Water makes a good dielectrum, whereas ions dont. Capacitive measuring therefore will have a better correlation with the actual amount of water in the soil than resistive measuring and, as said, ideally there will not be any corrosion.

Although the Arduino can measure capacity, it needs 3 pins for that. Also, it isnt really practical to have a long wire as part of your soil probe capacitor go to your Arduino as the wire and whether it is  straight or curly or in a loop, will act as a parasitic capacity and affect the measurement.
Putting your Arduino right onto your plantbed might also not be the best solution.

RC Oscillator With 74HCT14

A better way to do this is to introduce an RC oscillator in which the soil functions as a capacitor and the Arduino measures the frequency that comes out of the oscillator. More water  will increase the value of the ‘capacitor’ which usually will lower the frequency (or increase the cycle time) and that can be measured with the arduino.

An easy RC oscillator can be seen in the figure to the right. A 74HC14 or 74HCT14 Inverter Schmitt-trigger is all you need. For the HC version the Frequency is:
for the HCT version it is:

But in fact the frequency isn’t really that important because we are not making a frequency meter. We are only interested in changes of the frequency that relate to  dry, moist or wet soil. The workings of this type of Oscillator are explained here. and here. The theory behind the frequency calculation is explained here.

leydenjarI tested my set-up initially with a sort of Leyden Jar as a capacitor. Simply put I taped two pieces of alufoil on the outside of a glass jar, attached wires to it and tried if I could measure a change between an empty and a full jar. I started out using a 100k resistor, but only got a decent range after using a 2M2 resistor: an empty jar gave me 1uSec (maybe less, but I guess that was my lower limit) a half full jar around 50uS and a full jar about 100uS (measured with PulseIn). From using a known capacitor I knew I had to use the formula f=1/T=1/(0.67*R*C), but as said, neither the frequency or the actual capacitor value are of much importance as we are just looking for  changes.

Nevertheless the capacity of this jar (when full) could be calculated from
Now ofcourse this isn’t entirely correct as with PulseIn We only measured half a cycle, so in fact the Capacity is more likely to be 136pF, provided the dutycycle is 50% (some sources say it is 50% others say it is 33% with the space  2*mark).

byte pin = 8;
unsigned long duration;

void setup()
  pinMode(pin, INPUT);

void loop()
  duration = pulseIn(pin, HIGH);
  Serial.print("Time ");
  Serial.print(" usec ");
  Serial.print(" kHz ");
  Serial.println(" Hz");

Then it was time to do some garden field tests. There are several ways to construct a probe: two pieces of PCB at a distance from eachother, One piece of PCB with two plates etched onto it, or a piece of double sided PCB. With regerd to the latter, we tend to think of a capacitor as two plates with a dielectrum in between, but in fact it can also be two  plates with a dielectrum around it.

capacitive probe-textMy garden field test, using two insulated plates of PCB (picture) kinda gave similar results as with the Leyden Jar so I knew I had a decent design.

Yet, two plates is not really very handy: you have a loose wire connecting the plates and as that forms part of the capacitor it introduces stray capacitance, so I decided to go for either a double sided PCB, or a single sided PCB with two plates etched onto it and then place the oscillator on that PCB as well. Frankly, that idea isnt new as many of the (semi)DIY (e.g. the ‘Chirp’) or commercial capacitive probes follow that design as well.

Now it is always good  that before you make a PCB to think through what you want. As I was using only 1/6th of the 74HCT14, I was thinking maybe I could use the other gates as RC oscillators as well  for e.g. an LDR or NTC. Now ofcourse I immediately dismissed that again as I could just as well use an analog read of those and I would have to run extra cables that would all carry a frequency signal, no doubt those would interfere, but it got me thinking. The ‘Chirp’ has a big brother that has an I2C interface, if I would add that, I could add some other sensors (light, temperature)  to my probe. With just the capacitive sensor I would have to run 3 wires (+Vcc, signal, ground). With I2C 4 wires (+Vcc, SDA, SCL, Ground) would be enough for a number of sensors on my probe. Also, as I have various plantbeds, having a number of I2C probes wouldnt require  more inputs on my Arduino.

Obviously, adding I2C meant adding a microcontroller, preferably a cheap one, which easily brings one to the attiny25/45/85 series. If you have good eye sight and a steady hand, you could consider the soic version that is available from 30-70 cts. If you go for a DIP version, that is around 0.9-1 euro. Considering one can get an entire Pro Mini for about 1.20, obviously that is a narrow gap and I (or you) could consider giving each plantbed a totally dedicated  Pro Mini microprocessor that could take care of the irrigation as well.
Having said that, in the past, I have made a self contained system for plantbeds, just using 1 Opamp, so maybe I should just consider this I2C excercise a ‘learning excercise’

capacitive74HC14_attinyI came up with the following circuit. It is easy to recognise the RC oscillator. The cycle signal is fed to PB1 whereas the analog inputs on PB3 and PB4
A3= PB3=physical pin2;A2=PB4=physical pin3.
Pin PB2 is used as SCL signal and PB0 as SDA signal for the I2C interface.

If for any reason you do not have a 74HCx14 in your toolbox, there are other ways of constructing an RC generator. E.g. a 555 or a 74HC00. Even a single transistor could be used. With this type of oscillator the dutycycle approaches 50%


In a next article I will discuss how to implement the I2C software.

Using FET’s to Switch a load

Earlier I wrote a post on using MOSFET’s with TTL levels and  on using MOSFET’s to drive Powerleds. Now I will write a bit more on using MOSFET’s to Switch a load.

The simplest way is the circuit below:NFET1It shows a basic circuit with an N-MOSFET that drives a relay. As a relay is an inductive load, the fly-back Diode D1 is necessary  to protect the FET.
If we presume the input signal is on a TTL level, the FET needs to be a ‘logic FET’ that switches on these levels.
To avoid ‘floating’ of the input, we make sure that without any input signal the Gate of the FET has a defined low level by adding resistor R2. The value of this resistor is not very critical.
With regard to the gate resistor R1, there is a lot of discussion whether this is necesary or not, but as it limits the current surge when a load is applied I have chosen to add one.
There is also  discussion on whether the gate resistor should be placed to the left of R2 instead of the right, but that is not necessary, and not critical. Should it be on the left, R1 and R2 would form a minimal voltage divider and as R2 is solely there to define a logic state and R1  only to protect the gate, they can stay as is.
The value of R1 is also not very critical: at 150 Ohm the current is limited to 5/150= 33mA which is still within the 40mA spec of the Arduino (mind you, this is an extreme case as the Gate  resistance is very high). Upon increase of the value of R1, it takes longer to send the FET in saturation, which increases the RDS value, causing the MOSFET to get hotter.
Let’s take the IRL520NSP as example for our calculation: As the input capacity of  MOSFET is 440pF (datasheet page 2/11), the time it would take for the FET to reach saturation would be:

t=2.2 * 440*10-12 * 150
t=145.200 *10-12
t=145 *10-9

Though the MOSFET, once in saturation is a pretty good switch, there still is a minimal resistance called RdsOn. To make sure the FET can handle the load, we have to calculate the power that will be dissipated in the FET. As a relay as in the example usually doesn’t use that much current, lets presume we want to switch a device that draws 4 Amps. For the logic FET we have chosen- the IRL520NSP- the specs are:
RdsOn=0.22 Ohm @VGS=5V @ Id=6Amp.
The power dissipated in the FET is then P=I²*R=4x4x0.22 =3.52 Watt.
That is well within the specs of the FET.
thermalresistanceIn order to calculate how hot the FET will be (and to see if we need a heatsink), we need the “Thermal Resistance Junction to Ambient” (RØJA). For our FET that is 40°/Watt, so that means a temperature rise of 3.52*40=140.8 degrees. Thus at an ambient temperature of 20 degrees that will be 161°C. The TjMax (maximum Junction temperature) for this FET is 175°C so that would be just within spec. A decent heatsink would not be a luxury in this case. Mind you though that many modern MOSFETS’s have a gate capacitance that is much lower, in the range of 10-15pF

In the above example the FET was sinking the current. This means that the Vcc was ‘sourcing’ the  current to the load, whereas the FET was providing the connection to ground, i.e. ‘sinking’ the current.

Sometimes it may be necessary to ‘source’ the current, for instance if we need the  grounds of two digital circuits to be galvanically connected, but we want to be able to switch off one of the circuits. A battery operated Attiny with an Rf transmitter attached might be a practical example: in order to save the battery, the transmitter needs to be switched off when it doesn’t need to be active.

In that case we ‘source’ the current to the ‘+’  of that circuit, that is galvanically connected to earth where it ‘sinks’ the current. A common cathode RGB is another example that would need this.
Sourcing current can be done with a p-FET. A Logic Level P channel MOSFET is e.g. the TPS1110 with an RdsOn of 65mOhm at -4.5Volt at 6 Amp. Another Logic Level MOSFET is e.g. The IRL6402 or the IRLR9343, but the latter is more suitable for audio amplifiers. The IRL6402 also does have a very low RdsOn of 65mOhm at 4.5Volt (and 3.7 Amp)


The circuit doesnt differ that much from the ‘sinking’ circuit with the N-FET. It is in fact everything flipped over its horizontal axis (but the direction of polarity for the diode remains). The circuit is OFF when the Gate is the same voltage as the Source (VGS = 0), which means that we have to output 5V (HIGH) from the Arduino to turn the MOSFET off. To turn it on we need -5V at the Gate (relative to the Source) so we need to output 0V (LOW) from the Arduino to turn the MOSFET on.

If we briefly go back to the  ‘sinking’ circuit with the N-FET, it is clear that it doesnt really matter what the required Voltage of the Load is: 5V, 12 Volt, 30 Volt: as long as the Mosfet is able to handle it it doesnt make any difference for the arduino (provided  that has its own 5 Volt supply).
The sourcing/P-FET circuit however does face a problem if the supply voltage goes up.
Suppose the supply Voltage is 12 Volt. Then our 5Volt TTL level will never be high enough to make VGS equal to 0 (relative to the source, so 12 Volt). It will  0Volt (Arduino pin LOW) or 5 Volt (Arduino pin HIGH), ergo the MOSFET will never be OFF.
The next circuit will solve that:


In this circuit we use a simple signal transistor to Switch the VGS between 5 and 0 Volt (relative to the source so 7 Volt or 12 Volt relative to ground). If the Output from the Arduino is HIGH, the transistor will conduct and the voltage on the collector will become LOW, causing the VGS to increase (remember, it increases in relation to the Vcc). If the Output from the Arduino is LOW, the transistor will not conduct, pushing the Collector voltage  towards Vcc, or in other words: lower the VGS, thus closing the FET and switching the Load OFF. This also has the  advantage that in comparison with the prior circuit, the signal is no longer inverted: Arduino pin HIGH => load ON. Arduino pin LOW => Load OFF. Another ‘advantage’ is that at a higher voltage also non-TTL level MOSFETs can be used.
The calculations on this circuit are as follows:
The base transistor limits the current to

=4 mA

As the Arduino pin will have no trouble sourcing that, the BC547 will be in full saturation.The Collector Emittor saturation voltage is 0.2 Volts. Therefore the Vcollector and thus the Vgate will be 0.2 Volts, in other words the VGS will be 11.8 Volt, which is more than enough to send the MOSFET in saturation.
As a double check: The current through the resistor will be 11.8/1000=11.8mA
lets presume the gain of the transistor is around 100 (it depends a bit on the type of BC547 and the current range in which we are working), the Ib will then need to be minimally 11.8uA, which is sufficiently met by the current of 4mA.

If we want to calculate the power and heat development in the transistor we do that as follows:

P = (VBE * IBE) + (VCE * ICE)
RØJA = 200 °C/W (from datasheet)
Temperature increase= (10.8*200)/1000=2.16°C

This works well, untill the Supply Voltage goes up to above 12 Volt. That is not some magical number, but it is in general the max VGS the FET’s can take. The TPS1110 for instance has already maximum rating of 7 Volts.

The circuit below gives a solution:

We calculate the circuit as follows: If the Arduino goed HIGH. there will be 5 Volt on the base of T2. Therefore there will be 5-0.7=4.3 Volt on the emitter. Therefore the current through R2 is:

4.3 / 330 = 13 mA

With an hFE of 100, about 99% of that current will flow through the collector as well and thus through R1. This would normally mean a voltage drop of 13 Volt over R1. Because we have a zenerdiode, much of that current will flow through the zener, when it tries to maintain the voltage drop to 10 Volt over VGS.

The function of the 1 k resistor (R1) is then mainly to pull the gate quickly back up to the supply voltage and thus  VGS = 0 if the transistor is off. R2 is there mainly to create a current that can activate the Zener without the zener having to dissipate the full Vcc

It is important that the MOSFET be switched on and off quickly, as it has low power dissipation when fully off (ie. no current flowing) or fully on (when there is a low resistance between gate and drain). At other times the power dissipation will be higher, and the part may get hot.

This won’t be an issue for low-switching speeds (eg. turning garden lights on and off, or a fish feeder) but becomes an issue when doing PWM (pulse-width modulation) where you may be switching on and off many times a second.

The analogWrite function on the Atmega328-based Arduinos runs by default at 490 Hz. Tests indicate that the circuit above will take about 1 µS to switch on and 8 µS to switch off (if using the high-side driver) and 1 µS to switch both on and off if using the low-side driver. (High side means your switch/FET is between the Vcc and the load; low side means the switch/FET is between the load and ground.)

This is one of the reasons for choosing a reasonably low value for R1 in the high-side driver. We rely on R1 to pull the gate of the MOSFET high when the transistor is turned off, and we need that done as quickly as reasonably possible. We could potentially use a lower value resistor for R1 (eg. 470 ohms) to increase the switching speed, but then Q1 (the driver transistor) has to switch higher currents, and we need to watch that this transistor (Q1) does not get too hot.

Another point which can be initially confusing is expecting the Arduino board to provide enough power to run a motor, or lots of LEDs. It won’t, basically. The power supply on the Arduino is rated with enough capacity to drive the chips on the board itself, with a little over for extra chips like clocks, SD cards, etc.

It is not intended to drive a 3 amp electric motor.

In this case you have a separate power supply (maybe a battery, maybe a plug-pack) which is the “+5V” or “+12V” on the circuits above.

However it is important to connect the grounds. That is, connect the ground wire from the battery or plug-pack to the ground wire on the Arduino. That way they have a common “reference voltage”.