Category: Arduino

Update for library PAM_WiFiServer

Update for library PAM_WiFiServer

An update to the PAM_WiFiServer library which will generate a settings.htm page based on the variables created with the PAM_Tools library. This way if you log variables using the PAM_Tools library, you can also easily maintain them with this function. Think for example of an API key or timeout parameters.

Example 2 is an elaborate example of how to use this function.

github-mark-32px Available on GitHub with a lot of comment in the code. Direct download.

Advertisements
Update for library PAM_WiFiConnect

Update for library PAM_WiFiConnect

I recently had a short power outage. Nothing major but a feature request for the connect library did come out of that. When the power came back on, my ESP with my temperature logger was back on faster than my wifi which meant that after the wifiConnect nothing else happened. Ok, I could have coded that in the program but than I realized that if you have some sort of IoT device, it does not make sense to return to the setup function from the wifiConnect if you have no wifi. A need was born.

The result? A function called waitWiFiConnect which does what it’s name implies; it waits for a wifi connection. It does this by turning on the internal led, GPIO2, try to connect via wifiConnect. When it returns from that function it checks whether there is a connection. If there is a connection the led is turned off and the function ends. If not, the led blinks shortly after which we wait for 1 minute before trying again. It will only return to the caller after it has a wifi connection.

github-mark-32px Available on GitHub with a lot of comment in the code. Direct download.

Arduino IDE libraries

Arduino IDE libraries

After creating my initial library, I saw it grow rapidly with more generic functions I wanted so instead of staying with one library which could grow out of proportion (from a code size perspective), I decided to create a library for each of my needs (which of course makes sense from a lot of angles). So far this I have created the following libraries (so far mostly aimed at the ESP8266):

  • PAM_Tools
    This library contains functions to access the file system to store and retrieve information;
  • PAM_WiFiConnect
    This library contains functions to easily connect to the wifi, including selecting one of multiple access points;
  • PAM_WiFiClient
    This library contains functions to easily retrieve a webpage;
  • PAM_WebAPI
    This library contains functions to use web based APIs such as IFTTT and ThingSpeak.
  • PAM_WiFiServer
    This library contains functions for creating a webserver.

 

Library PAM_WiFiServer

Library PAM_WiFiServer

After working with the Arduino IDE for some time, I decided it is time to write some convenient libraries that will help me quickly do some of the tasks that occur often and could do with a convenient wrapper.

This library is there to easily create a webserver.

github-mark-32px Available on GitHub with a lot of comment in the code. Direct download.

Let’s look at the functions:

void wifiServerStart()

This function needs to be called once before you use any of the other functions.

bool serverRequestReceived()

This function you should call frequently in your loop function. If true, you should create a webpage to be send back using the other functions.

String pageRequested ()

You can call this function if a serverRequestReceived returned true and it will return the name of the page that is requested.

String giveURLParam (String search)

If a serverRequestReceived than you can check with this function whether a specific parameter has been send. It will return the value of that parameter or PARAMNOTFOUND if the parameter is not in the list. This function is used to get the values submitted for example throught a form.

void serverSendPage (String paramName[], String paramValue[], int paramCount, String pageName)

This is the function that sends back a page. The way it works is that a pageName is retrieved from the filesystem /page/<pageName> and line by line each parameter given in paramName is replaced by the corresponding paramValue. So for every line retrieved, the function loops through all paramNames and replaces each instance of %paramName% with the corresponding value. The value paramCount should contain the number of elements in both paramName and paramValue. The pageName variable should contain the page that needs to be parsed and send back to the client.

There are multiple instances of this function defined. If no pageName is given, it is assumed to be index.htm. If no parameters are given, no parameter replacement will be done. If neither parameters nor a pageName is given, the file index.htm will be send without parsing.

If the requested pageName is not found, the headers will be send put the page will be blank.

 

Library PAM_WebAPI

Library PAM_WebAPI

After working with the Arduino IDE for some time, I decided it is time to write some convenient libraries that will help me quickly do some of the tasks that occur often and could do with a convenient wrapper.

This library is there to use different web based APIs such as that of IFTTT and ThingSpeak.

github-mark-32px Available on GitHub with a lot of comment in the code. Direct download.

Let’s look at the functions:

String ifttt (String event, String value1, String value2, String value3)

If This Than That, IFTTT, is a very extensive online tool that allows you to act on an event. The concept is based on channels that can send and receive data. A specific combination of channels and actions is called an applet.

There is also a channel called Maker which you can use for your own IoT devices. This is what this library is for. You get your own Maker key which you should put in the library PAM_Defines.h which is nothing more than a way for you to select which APIs are compiled in. If you don’t use IFTTT for example, you should also not have to overhead when compiling so if you do not define a key, the functions will be excluded from the library which should save memroy. I will not go into detail on IFTTT usage just now. Suffice it to say you need a key which you define in PAM_Defines.h:

#ifndef PAM_Defines_H
#define PAM_Defines_H

//
// This is where you define your own IFTTT.com key
//
#define IFTTTKEY "YOUR-KEY-HERE"

#endif

and you need an event type which defines what kind of trigger you want to send. I have also defined these in my PAM_Defines.h:

#define IFTTT_BOOT "PAM_BOOT"
#define IFTTT_HTTP "PAM_HTTP"
#define IFTTT_MSG "PAM_MSG"

There are multiple instances of the same function created in the library so you can call it with no values, one, two or all three.

As an example, I use the event IFTTT_BOOT to send me a message if an IoT device boots where I send it’s IP as value 1. If it also contains a webserver I use the event IFTTT_HTTP along with it’s IP as value 1 so the message can actually contain a link to the IP.

I use IFTTT_MSG to send a message, for example if my plant needs watering.

void thingspeak (String api, String field1, String field2, String field3, String field4)

void thingspeak (String api, float field1, float field2, float field3, float field4)

The next API included is that for ThingSpeak. ThingSpeak call themselves an open data platform for the Internet of Things. In order to work with ThingSpeak, you need to set up an account and than set up a channel. Unlike IFTTT, you need a different API key per channel so in the library I choose to have one define to say you want to use the library. I use seperate defines for each of my channels:

#define THINGSPEAK
#define TS_TEST "MY-API-KEY"

The #define THINGSPEAK is needed to compile this part of the library. Like IFTTT there are multiple instances of the library. You can call the function with just one parameter or up to four parameters (ThingSpeak actually allows eight but I have not set up for that yet. If it is needed, let me know). The API key is mandator as well as the first field. The API of ThingSpeak allows you to set a date time for the event and if you don’t current date time is used. Since I wanted to keep the library small, I did not implement the seperate date time parameter.

You can use String for the values or int/float.

Library PAM_WiFiClient

Library PAM_WiFiClient

After working with the Arduino IDE for some time, I decided it is time to write some convenient libraries that will help me quickly do some of the tasks that occur often and could do with a convenient wrapper.

This library can be used for easy webpage retrieval. You can do a fire and forget or parse through every line, with or without the header.

github-mark-32px Available on GitHub with a lot of comment in the code. Direct download.

Let’s look at the functions:

String getURLParse (String host, String url, bool fullContent, void (*g)(String l), int port)

This is the main function to retrieve a webpage. All other page retrieval functions call this function. You pass a host and a url, starting with a /, tell it whether to send just the body (false) or include the header (true) followed by a function which receives one String at a time which will be the retrieved String and finally a port. The port can be omitted in which case it defaults to port 80.

This function will send a request to the host asking for the specificed url. It will than retrieve every line of the page, it will determine where the header stops and the page begins and send it to the function g (only the body if that was requested in the boolean fullContent).

The last line received will be returned in the String.

String getURLFullParse (String host, String url, void (*g)(String l), int port)

This function will call the main function requesting to send all lines, including the header to the function g. The port is optional. If omitted it will default to port 80.

String getURLBodyParse (String host, String url, void (*g)(String l), int port)

The function will call the main function requesting to send all lines of the body of the page to the fuction g. The port is optional. If omitted it will default to port 80.

String getURL (String host, String url, int port)

The fire and forget version, get the url but do not use the resulting webpage. Again, the port is optional and will default to port 80.

void doSerial (String webLine)

If you are debugging it could be convenient to see what the host is sending back. If you use the function doSerial as the function to process your lines, you will see the page received on your serial monitor.

 

Library PAM_Tools

Library PAM_Tools

After working with the Arduino IDE for some time, I decided it is time to write some convenient libraries that will help me quickly do some of the tasks that occur often and could do with a convenient wrapper.

This library is aimed at using the file system to store keys.

github-mark-32px Available on GitHub with a lot of comment in the code. Direct download.

Let’s look at the functions:

The following four functions are used to store and retrieve String and int values persistently (meaning between reboots).

String getStringKey (String location, String key)

This function will retrieve the content of a file in a string where the filename is /<location>/<key>.txt The .txt extension is used so on Windows you can create
the needed files in a data directory which you can than upload using the ESP8266 Sketch Data Upload. If the key is not found a NOSTRINGKEYFOUND will be returned.

int getIntKey (String location, String key)

This function will retrieve the content of a file and put it in an int where the filename is /<location>/<key>.txt The .txt extension is used so on Windows you can create
the needed files in a data directory which you can than upload using the ESP8266 Sketch Data Upload. If the key is not found a NOINTKEYFOUND will be returned.

void putStringKey (String location, String key, String value)

This function will put a String value into the file with filename
/<location>/<key>.txt If the file exists it will be overwritten.

void putIntKey (String location, String key, int value)

This function will put an int value into the file with filename
/<location>/<key>.txt If the file exists it will be overwritten.

 

Library PAM_WiFiConnect

Library PAM_WiFiConnect

After working with the Arduino IDE for some time, I decided it is time to write some convenient libraries that will help me quickly do some of the tasks that occur often and could do with a convenient wrapper.

This library is aimed at easily connecting to wifi. I know that there are other libraries that support this but mine supports me better and might support you better too.

The library needs one other library, PAM_Tools.

github-mark-32px Available on GitHub with a lot of comment in the code. Direct download.

Let’s look at the functions:

void wifiConnect (String ssid, String password)

This function will connect you to the specified SSID using the specified  password. It is different from the standard connect to wifi and just waiting on a connected in two ways:

  • It will break trying to connect after 5 runs of 10 seconds waiting on a connection
  • It will disconnect from wifi and try again in every run.

In my experience some of the connections might not work in the first try (especially hotspots on a mobile phone) and by stopping the connection and starting again I noticed that most connections will succeed within 15 seconds.

I also wanted the wifi connection not to run forever but break off at some point so you could do some error handling.

void wifiConnect (String ssid)

This instance of the function will get the password for the specified SSID from the file system, through one of the functions in PAM_Tools, and than uses wifiConnect to connect to it.

Passwords are stored in a file on the file system in the directory wifi where the full name of the file will be /wifi/ssid.txt and this file will contain one line and that is the password for that ssid. There are two advantages to do this:

  • If you share your code and you forget to change your ssid to Your-SSID at least you will not have given away your password
  • If you have multiple ssid’s that you can connect to, which is what wifiConnect does if you do not supply any SSID, you do not have to have all SSIDs and passwords in your file.

void wifiConnect (bool debug)

This instance of the function in the library is probably the most powerful/convenient. What it does is scan the available networks and check for each one found whether there is a associated password stored in the file system. If so, it will try to connect.

You can list preferred networks by storing SSIDs in a numbered file in the same directory. So if there is a file called 1.txt in the wifi directory, it will open that file and check whether that SSID is available. If not it will try 2.txt etc. If none of them are available or there is no 1.txt then it will try to use any of it’s other credentials. If there is still no connection, it will try the SSID in 0.txt which could be a hidden SSID. I found this function works great if you have a mobile IoT device. Even with fixed devices I now use it and put my mobile hotspot as the first to check (1.txt). It usually isn’t on, but if I want to isolate the IoT, for example for testing, I can turn on my hotspot, reset it and it will connect to my hotspot.

If you want to see which networks are found and how it decides to connect to it, you can call it with a parameter true after which it prints out what it does on Serial.

void wifiConnect ()

This instance of the function in the library will call wifiConnect(false) and as a result try to automatically connect to a wifi network as described above.

Photo resistors, in depth

Photo resistors, in depth

Some time ago I bought 50 photo resistors, 10 pieces of 5 different types each. Had no real need for that many but it’s very cheap if you buy them through AliExpress. It turned out to be quite difficult to find out which resistor does what. Tried looking for photoresistors, LDR, Light Dependent Resistor, photo cell but I could not find any explanation on the different types.

I did find the following information (the table is compiled from different sources):

Model Light resistance
(10 Lux) KOhm
Dark resistance
MOhm
GL5506 2-6 0.15
GL5516 5-10 0.5
GL5528 10-20 1
GL5537 16-50 2
GL5539 30-90 5

But how does that help in connecting these things? Well, I decided to connect these things, all at the same time and look at the readings.

So connecting, how do we do that? Well, we need to understand (somewhat) Ohm’s law. To measure the amount of light, we want to measure the resistance of the light sensor. Unfortunately the Arduino or the ESP8266 do not measure resistance. They can however measure the voltage on an analog port and this is where we need Ohm’s law. First, let’s look at a schematic:

lightsensorconnect

We connect the photo resistor to +5V (or +3.3V) on one end and the other end on a analog port (the ESP8266 has one, the Arduino has many). We also connect that same end to a resistor (in my diagram a 10K resistor) and the other end of the resistor to ground. What does this do? Well, current will flow from +5V over the photo resistor, continue over the 10K resistor and than to ground. What we are going to measure is the voltage at the point between the photo resistor and the normal resistor. Ohm’s law states V=IR, voltage is current times resistance. The current flowing from +5V to ground over both resistors will be the same (the amount of current does not change midway a circuit). That’s the key to figuring out the current at our analog port and here is how.

We can calculate the total current that flows from +5V to ground by adding the resistors and plugging it in Ohm’s law. Let’s say the photo resistor currently has a resistance of 10KΩ. The total resistance of the circuit is 10KΩ+10KΩ = 20KΩ. V = 5V which means I = 5V / 20KΩ = 0.25 mA. So we now know that there is 0.25 mA running through the circuit. Now we can calculate V at our analog input. The voltage drop over the photo resistor is V = IR and we now know I and R. V = 0.25 mA * 10KΩ = 2.5 V drop so at our analog input we will measure 5V – 2.5V = 2.5V. With 2 equal resistances, it makes sense that in the middle you will have 2.5V. Let’s take the next step.

The resistance of the photo resistor goes down when there is more light, so let’s make it a little darker, say 30KΩ. Let’s recalculate:

Total R = 30KΩ + 10KΩ = 40KΩ
I = 5V / 40KΩ = 0.125 mAVoltage drop over photo resistor = 0.125 mA * 30KΩ = 3.75 V
We measure 5V – 3.75V = 1.25V at our analog input

So less light means less voltage at our analog input. Well this math is all fine, but what does this mean? Well, if we know the voltage at our analog input we can also do the reverse and calculate the resistance of the photo resistor, just do the reverse.

Let me quickly share the setup and the code I used to test the resistors. You can my setup at the top. It is an Arduino Nano (which has 5 analog ports) and the 5 sensors, the bottom is the 5506 and moving up all the way to the 5539 at the top. It might be a bit hard to see. All black wires are +3.3V, all the white are ground and the different colors are for each of the analog inputs. You can see that I followed the schematic 5 times and importantly, used five 10KΩ resistors. You cannot combine all of them on one. Please do not forget to connect 3.3V to ARef which gives a better ready is my experience.

The code is simple, initialize five ports and continously display the results of the ports. I have added a header row every 10 rows so I can copy and paste that:

github-mark-32px Available on GitHub with more comment in the code. Direct download.

//
// The number of steps after which the header is repeated
//
#define STEPCOUNT 10
//
// The current step count
//
byte step = STEPCOUNT;

void setup() {
  //
  // Setup serial
  //
  Serial.begin(115200);
  Serial.println("Ready");
  //
  // Set the reference for measuring the analog signals
  // For some reason I got incorrect readings without connecting
  // the 3.3v (on my Arduino Nano) to AREF and setting this
  // reference
  analogReference(EXTERNAL);
  //
  // Setup all analog inputs. We are using 5 which is the maximum
  // for the Nano on which I tested.
  //
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A2,INPUT);
  pinMode(A3,INPUT);
  pinMode(A4,INPUT);
}

void loop() {
  //
  // Increase our counter
  //
  step++;
  //
  // If we are over our STEPCOUNT then we repeat the header
  //
  if (step>STEPCOUNT) {
    //
    // The reference to the different photo resistors
    // GL5506, GL5516, GL5528, GL5537 and GL 5539
    //
    Serial.println("* 5506  5516  5528  5537  5539");
    step = 0;
  }
  //
  // Print all analog values to serial
  //
  Serial.print("  ");
  Serial.print(analogRead(A0));
  Serial.print("   ");
  Serial.print(analogRead(A1));
  Serial.print("   ");
  Serial.print(analogRead(A2));
  Serial.print("   ");
  Serial.print(analogRead(A3));
  Serial.print("   ");
  Serial.print(analogRead(A4));
  Serial.println();
  delay(250);
}

If we take the values it shows during daylight, inside the house:

* 5506  5516  5528  5537  5539
  975   969   774   619   218
  975   968   773   619   220
  975   969   773   618   216
  975   968   771   616   215
  975   968   771   617   221
  975   969   774   620   226
  975   969   776   622   225
  976   969   775   621   221
  975   969   774   619   220
  975   969   774   619   219
  975   968   772   617   216

As you can see, the values are relatively stable. So let’s take one of the values of the 5528, 775. How do we calculate the resistance from that? The analog port has a 10 bit resolution, which means it can go from 0 to 1023. 1023 will be at 3.3V (in my case. If you use a Uno for example it will be 5V). The reading is 496 which means it is reading a voltage of 775/1023*3.3V = 2.5V. So we know the voltage drop was 3.3V-2.5V = 0.8V. So we know V. Now we need to know I and from that we can calculate R. We can calculate R because we know V and R for the other part of the setup, the 10KΩ. I = V/R = 2.5V / 10KΩ = 0.25 mA. Now we take that 0.25 mA and use it for calculating the resistance of the photo resistor.
R = V/I = 0.8V / 0.25 mA = 3,200 Ω. Now you can go to the GL5528 datasheet and see

gl5528

that the amount of light is between 30 and 85 lux. Well, that’s quite a broad range and not really useful for calculating the amount of lux but the deviation of these sensors might vary piece to piece but do not vary that much per piece, so if your sample decides to be more towards the dark side, it will be there with higher or lower light settings as well. What this means is that the sensors are great for detecting deltas in light even though getting a precise lux reading is not really feasible. Ok, well than we need more readings:

light from a normal bulb:
* 5506  5516  5528  5537  5539
  974   967   739   623   279
  982   981   844   717   437
  992   988   870   751   454
  994   991   874   758   440
  995   991   873   752   325
  992   986   836   700   137
  985   979   795   654   62
  978   972   754   610   34
  971   969   792   668   379
  988   985   854   727   440
  993   990   871   749   440

light from a mobile phone
* 5506  5516  5528  5537  5539
  1006   1007   956   925   795
  1006   1007   956   925   796
  1006   1007   956   925   797
  1006   1007   956   925   797
  1006   1007   956   926   798
  1006   1007   955   925   795
  1006   1007   956   925   796
  1005   1007   955   924   795
  1006   1007   955   924   793
  1005   1007   955   925   796
  1005   1007   955   925   795

light at dusk
* 5506  5516  5528  5537  5539
  834   834   385   208   20
  840   838   394   216   22
  840   840   402   222   23
  840   840   405   225   24
  839   839   404   225   24
  839   838   404   224   23
  840   838   405   225   24
  841   839   405   226   24
  841   839   405   226   24
  844   840   406   227   24
  845   840   406   227   24

light in the evening
* 5506  5516  5528  5537  5539
  582   583   118   52   1
  581   582   118   52   1
  580   583   118   53   1
  580   582   118   52   1
  580   581   118   52   1
  578   580   117   52   1
  577   577   116   52   1
  565   561   109   49   1
  584   583   118   51   1
  586   587   120   53   1
  589   590   121   53   1

There are a few things to notice. First, I thought it was interesting to see that the values fluctuated with a normal bulb. This sample was not an incident, it was doing that the whole time. I think it might have to do with the fact that light bulbs fluctuate because of the way the alternating current alternates but I’m not sure. The second thing to notice is that the 5506 does not really vary that much with light, especially compared to the others. It’s not because it’s broken, but it’s because it’s resistance is small compared to the 10kΩ resistor which means it does not leave a lot of ‘bandwidth’ to show it’s capabilities.

Maybe I will do some more readings where I take a resistor to match each photo resistor and see what the results are than.

Fun with HC-SR04 and WS2812

Fun with HC-SR04 and WS2812

After I managed to get the distance sensor HC-SR04 working and got the LED circle based on WS2812 working, I felt it was time to combine them in a fun project.

I connected two LED circles, 16 LEDs and 12 LEDs where the DO of the 16 went into the DI of the 12. What I wanted to do is in the outer circle have a red circle run in circles where the speed was dependant on the distance of an object in front of the sensor. The closer the object, the faster it moves. The inner circle shows the distance to the object. The farther the object, the more LEDs would light up.

github-mark-32px Available on GitHub with more comment in the code. Direct download.

The code for the Arduino IDE:

//
// The library from Adafruit which enables the use of the WS2812
// or NeoPixel
//
#include <Adafruit_NeoPixel.h>

//
// The pin the circle of WS2812 leds is connected to
//
#define CIRCLEPIN 6
//
// The number of leds in our two circles (12+16)
//
#define PIXELCOUNT 28

//
// Initialize the Adafruit library
//
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXELCOUNT,CIRCLEPIN,
  NEO_GRB+NEO_KHZ800);

//
// The current position
//
int degree = 0;

//
// The trigger and echo pin for the HC-SR04
//
#define TRIGGERPIN 13
#define ECHOPIN 12

//
// How long we delay before the next read and update of the leds
//
int delayMove = 50;

void setup() {
  //
  // Start the led string and turn them all off
  //
  pixels.begin();
  for(int i=0;i<PIXELCOUNT;i++){
    pixels.setPixelColor(i, pixels.Color(0,0,0));
  }
  pixels.show();
  //
  // Prepare the HC-SR04 pins
  //
  pinMode(TRIGGERPIN, OUTPUT);
  pinMode(ECHOPIN, INPUT);
}

void loop() {
  //
  // Determine the distance between object and HC-SR04
  // Read about it in more detail on
  // https://piandmore.wordpress.com/2016/10/04/arduino-hc-sr04-ultrasonic-distance/
  //
  long duration, distanceCM;
  digitalWrite(TRIGGERPIN, LOW);
  delayMicroseconds(5);
  digitalWrite(TRIGGERPIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGERPIN, LOW);
  duration = pulseIn(ECHOPIN, HIGH);
  //
  // The distance in cms
  //
  distanceCM = (duration/2) / 29.1;
  //
  // Turn all pixels off
  //
  for(int i=0;i<PIXELCOUNT;i++){
    pixels.setPixelColor(i, pixels.Color(0,0,0));
  }
  //
  // Turn on the inner circle leds
  // 1 led for every 2 cm of distance
  //
  for (int i=16;i<16+distanceCM/2;i++) {
    pixels.setPixelColor(i, pixels.Color(0,50,0));
  }
  //
  // Determine the current position led of the outer circle
  // and turn on the required leds
  //
  int thisPixel = (degree*16)/360;
  pixels.setPixelColor((thisPixel+3)%16,pixels.Color(255,0,0));
  pixels.setPixelColor((thisPixel+2)%16,pixels.Color(100,0,0));
  pixels.setPixelColor((thisPixel+1)%16,pixels.Color(40,0,0));
  pixels.setPixelColor((thisPixel)%16,pixels.Color(15,0,0));
  pixels.show();
  //
  // Depending on the distance of an object, make the circle move
  // faster (if it is closer) or slower (if it is farther away)
  // and take the maximum time of it is very far away or
  // if there is no object
  //
  if (distanceCM>=200) {
    delayMove = 200;
  } else {
    delayMove = distanceCM;
  }
  delay(delayMove);
  degree += 10;
  if (degree>=360) {
    degree -= 360;
  }
}

The code looks a lot like the two earlier mentioned codes combined. What is added is the 12 LEDs which, as you can see, are addressed as being the next 12 on the same string as the 16.