Friday, May 31, 2019

Ping Ping Anybody Home ???

For a complete index of all my stories click this line

A nice feature of the Philips Hue lamps is called Geofencing. This just means that you can instruct the Hue bridge to automatically switch your lights on when you are approiaching your house. So for a time I wondered how they do that. And in fact it is very easy.

It is a technique that can be used for many different purposes. Not only to test if you are around but this also makes it possible to test wether your wireless apparatus are actually functioning.

It's called ping.

Ping

Ping is a network function that sends a command to an IP adress. If the device with that IP adress is connected to the router you will get a response. If the device is off (not connected) then you will get an error back.

It is even possible to ping web-adresses. That way you can see if a certain server on the web is on-line.
If you for example want to test wether this web-log is still on-line you could use something like the next command:
ping("http://lucstechblog.blogspot.nl/")

Ping Ping Anybody Home ?

So how is that going to tell me wether anybody is home or nearby. Well simple. Most people I know always carry their mobile phone around. So do I. And most of the time wifi is turned on. So if I give my phone, and for that my girlfriends phone etc, a fixed IP adress in my router I can Ping that IP adress et voila.

Give your home mates a fixed IP adress.

Start with opening the IP adress of your router in your browser. In my case my router has IP-adress 192.168.1.1 Your's may vary so look it up in the manual.



Enter the ip-adress in your browser and if you have a Zyxell router like I do you will be presented the above screen. Different routers give different results, but it should be easy to find the page that shows all connected devices.

As you can see I have given all my networked devices meaningfull names. So let's look at the details of my phone.



First you can see my phones IP-adress and as you can see I checked Static DHCP. This makes sure that everytime my phone connects to the router it will get the same IP adress.
Do this for all the phones and wireless apparatus in your home.

Ping ??

Ping is a wifi function. In some languages it is build in (yes in Basic) and in some languages it is not. What I wanted is to have my ESP Ping my devices and depending on the outcome switchs led's (relay's) on or off.

Standard C++ (Arduino) for the ESP has all kinds of Wifi functions build in but no Ping.

Fortunately Daniele Calanardi has build a library that we can use. You can download that library from the following link: https://github.com/dancol90/ESP8266Ping

Unpack the library and place it in your \Arduino\libraries folder and start the Arduino IDE.

Circuit



The hardware is simple just an ESP8266 (I used a NodeMCU) and 4 leds connected through 220 Ohm delimiting resistors. The led's are attached to D0, D1, D2 and D4.

The Arduino source



/*
 * Anybody Home ??? 
 * This program tests IP numbers with PING to see if they are
 * active. If so the Led will be on if the IP number is not
 * active the Led will be off
 * This way we can check activity and person presence
 * Written by Luc Volders
 */

#include 

<ESP8266WiFi.h>
#include 

<ESP8266Ping.h>

const char* ssid = "XXXXXXXXX";
const char* password = "YYYYYYYYY";

const IPAddress thermometer(192, 168, 1, 65);
const IPAddress domoticz(192, 168, 1, 66);
const IPAddress Lucsphone(192, 168, 1, 70);
const IPAddress elsphone(192, 168, 1, 72);

void setup() 
{
  pinMode(D0,OUTPUT);
  digitalWrite(D0,LOW);
  pinMode(D1,OUTPUT);
  digitalWrite(D1,LOW);
  pinMode(D2,OUTPUT);
  digitalWrite(D2,LOW);
  pinMode(D4,OUTPUT);
  digitalWrite(D4,LOW);
  delay(10);

  // Start by connecting to our WiFi network

  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED)

 
  {
    delay(100);
  }
}

void loop() 
{  
  if(Ping.ping(thermometer)) 
    {
      digitalWrite(D0,HIGH);
    } 
  else 
    {
      digitalWrite(D0,LOW);
    } 
  if(Ping.ping(domoticz)) 
    {
      digitalWrite(D1,HIGH);
    } 
  else 
    {
      digitalWrite(D1,LOW);
    }  
    if(Ping.ping(Lucsphone)) 
    {
      digitalWrite(D2,HIGH);
    } 
  else 
    {
      digitalWrite(D2,LOW);
    }  
    if(Ping.ping(elsphone)) 
    {
      digitalWrite(D2,HIGH);
    } 
  else 
    {
      digitalWrite(D4,LOW);
    }  
  delay(1000);
}
    


Let's look closer to the program.

#include <ESP8266WiFi.h>
#include <ESP8266Ping.h>

to activate the wifi functions of the ESP we need to include the Wifi library and for Ping we need to include the ESP8266Ping.h library.

const char* ssid     = "XXXXXXXXX";
const char* password = "YYYYYYYYY";

Fill in your router's credentials so you will connect to your network automatically.

const IPAddress thermometer(192, 168, 1, 65);
const IPAddress domoticz(192, 168, 1, 66);
const IPAddress android(192, 168, 1, 70);
const IPAddress elsphone(192, 168, 1, 75);

Look in your router for the IP adresses of your Wifi Devices and replace the ones I have used.

The rest of the program is straighforward.

  if(Ping.ping(Lucsphone))    
    {                         
      digitalWrite(D2,HIGH) ; 
    }                         
  else                        
    {                         
      digitalWrite(D2,LOW);   
    }                         


In the loop all devices are pinged. In this part the IP number of my phone is pinged. If it is present Ping will respond with a 1. If I am not at home Ping will respond with a 0 and the led will be set on or off accordingly.

This can be optimized :

digitalWrite(D2,Ping.ping(Lucsphone));

However I wanted the code to be easy to follow for less experienced C++ programmers.

Basic program

Naturally (I know some loathe this) I wrote the same program in ESP-Basic which is my favorite rapid software devellopment platform. So I hereby give you the simple code that does the same as the C++ program:



io(po,D0,0)
io(po,D1,0)
io(po,D2,0)
io(po,D4,0)

timer 1000, 

[testping]

wait

[testping]

io(po,D0,ping("192.168.1.65")) 'thermometer

io(po,D1,ping("192.168.1.66")) 'domoticz

io(po,D2,ping("192.168.1.70")) 'luc's phone

io(po,D4,ping("192.168.1.72")) 'els phone

wait


Let us look at some details.

io(po,D0,0)
io(po,D1,0)
io(po,D2,0)
io(po,D4,0)

These lines set all the leds in the initial state which is off.

timer 1000, [testping]

This line initiates a timer that every second (1000 miliseconds) jumps to the routine testping.

io(po,D2,ping("192.168.1.70")) 'luc's phone

This line actually tests whether my phone is detected by the router so if I am in. Depending on the
feedback it sets the led on or off. Replace the IP numbers with your own.

That's all folks.

Just for usability I modified the program so it has a webpage on which the information is displayed as wellas leds giving the information. So if you are around the ESP the leds will show what's happening and if you are not in its neighbourhood you can check the webpage.


io(po,D0,0)
io(po,D1,0)
io(po,D2,0)
io(po,D4,0)

timer 1000, [testping]

wprint |<body style="background-color:powderblue;">|
wprint |<H1><span style="color: red;">|
wprint "Anybody Home ??"
wprint "</H1>"
wprint "<h3>Thermometer  "

textbox therm
cssid htmlid(), "background-color:powderblue;border-style: hidden;font-size: 16px;display:block;width:80px"

wprint "<br>"
wprint "Domoticz         "
textbox domo
cssid htmlid(), "background-color:powderblue;border-style: hidden;font-size: 16px;display:block;width:80px"

wprint "<br>"
wprint "Luc's phone      "
textbox lucphone
cssid htmlid(), "background-color:powderblue;border-style: hidden;font-size: 16px;display:block;width:80px"

wprint "<br>"
wprint "Els phone        "
textbox elsphone
cssid htmlid(), "background-color:powderblue;border-style: hidden;font-size: 16px;display:block;width:80px"

wprint "<br>"
button "QUIT", [progend]
wait

[testping]
therm = ping("192.168.1.65")
if therm = 1 then
io(po,D0,1)
therm = "available"
else
io(po,D0,0)
therm = "off line"
endif


domo = ping("192.168.1.66")
if domo = 1 then
io(po,D1,1)
domo = "available"
else
io(po,D1,0)
domo = "Domoticz off line"
endif

lucphone = ping("192.168.1.70")
if lucphone = 1 then
io(po,D2,1)
lucphone = "at home"
else
io(po,D2,0)
lucphone = "he's not in"
endif

elsphone = ping("192.168.1.72")
if elsphone = 1 then
io(po,D4,1)
elsphone = "available"
else
io(po,D4,0)
elsphone = "she's out"
endif

wait

[progend]
io(po,D0,0)
io(po,D1,0)
io(po,D2,0)
io(po,D4,0)
end

The result.





Modifications.

Use your imagination.

You can send the information to cloud-based IOT servers like thingspeak (look for a tutorial here:
https://lucstechblog.blogspot.nl/2017/11/thingspeak.html )

Replace the leds with relays so the lamps will go on if you approach your house.

Send the information to your home-automation system (like Domoticz which I am using) so
it can alter your thermostat settings or switch on your lights etc.

Till next time.
 

The next few weeks I am off on a long-earned holliday. There is however enough material on this web-log to get you going and start experimenting. So till July and remember:

Have fun !!

Luc Volders

Friday, May 17, 2019

At last.....but only dutch for now

For an index to all my stories click this line

Just a short entry today because today was the day I was eagerly waiting for.



By mail I received the proof of my book. So I spend the day checking if everything
was well. And boy I loved it. The print was crisp and clear. 
368 Pages information on the ESP32. From installing the software on your PC to building your own webserver to control lamps, motors etc and remotely read your sensors.
All written in the Arduino language (C++) with breadboard schematics made in Fritzing.

For now only in Dutch. I am working on the English version.

It will be available in bookshops and websites, on demand, throughout the Netherlands in the next weeks, when I finish checking and give the green light for publishing.

So if you want to buy one, send me an email : lvolders@gmail.com
As soon as it is available I will give you notice. Just state wether you want to buy the Dutch or English version. The english version will be available through a yet to be chosen publisher.

Nederlands

Vandaag is de dag waar ik al een tijdje naar uitkeek !!!
Ik ontving per post de drukproef van mijn boek: ESP32 uitgelegd.
Ik ben nu aan het controleren of ik er nog ernstige fouten in tegenkom en daarna kan het gepubliceerd worden. Dat zal nog een paar dagen tot maximaal 2 weken duren.

Het boek heeft 368 pagina's met informatie over de ESP32 van het installeren tot het maken van een webserver waarmee je motoren, lampen etc kunt bedienen of je sensoren uitlezen. Alles in C++ de bekende Arduino taal. Het is een werkboek voor beginners met veel uitleg, een of meer oefeningen aan het einde van elk hoofdstuk en ideeen voor projecten die je met de informatie uit het boek kunt bouwen.

Als je het wil kopen, stuur dan een mail naar: lvolders@gmail.com
Zo vlug als het echt beschikbaar is krijg je dan een berichtje van mij. 
In Nederland zal het boek te koop zijn bij boekhandels, webshops als bol.com en via de webshop van de drukker. Als elektronica winkels of fablabs geïnteresseerd zijn kunnen ze ook contact met mij opnemen.

Luc Volders

Friday, May 10, 2019

MP3 Player - stand alone

For an index to all my stories click this line

I know they are getting a bit outdated but there are still some uses for them: MP3 players. And sometime ago when I was surfing the net (who uses that expression nowadays.....) I stumbled upon a great MP3 module.



The module is sold and documented on the internet by several names. The first name is MP3-TF-16P and the second name is the DFPlayer Mini. Both seem to be exactly the same module.

So what is it.

It is an MP3 chip with an SD card reader on one module. The module is breadboard friendly and can be powered by any voltage between 3.2 to 5 Volts. So suitable for Arduino and ESP8266 projects. Next to that it has an onboard 3 Watt amplifier so you can direct attach a speaker. There is also a headphone / amplifier output with which you can attach a headphoe or attach it to your home stereo set.

The module supports MP3 and WMV decoding and sampling rates up to 48khz. The SD card supports FAT16, FAT32 up to 32GB with a maximum of 100 folders with each 1000 songs. The speaker and headphone connectors are attached to a 24 bit DAC with a dynamic range up to 90dB

Besides all this the module can be controlled by digital I/O ports, a resistor cascade on analog ports and by a serial interface.

Last but not least there seems to be an USB interface build in. I have found however no information or documentation on that up to now.

All in all pretty amazing specifications for a module that (at this moment) can be bought for about 1 dollar / euro from our favorite chinese suppliers !!!




Controlling the MP3-TF-16P

Like I mentioned above there are 3 methods to control this module.

- Using switches on the digital I/O pins
- Using switches with a resistor cascade on 2 analog inputs.
- Sending commands over the serial interface

As there are digital I/O pins the module can be controlled by an Arduino or an ESP8266. This can also be done by sending commands over the serial interface. There is an Arduino library available for that.

The resistor cascade needs some explanation.

Basically a range of resistors is connected to Ground. The remaining pin is connected to a switch which is connected to one of the analog inputs. Pressing a switch will therefore send an electric signal which value is dependend on the resistor value. This will trigger a specific command.
 


I think the schematic explains all.

You can find more information in the manual for this module which can be found here:

https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299

A minimalist MP3 Player

I started with building a minimalists MP3 Player.

The only things you will be needing to build this are:

- battery holder for 3 AA batteries
- a breadboard
- some breadboard cables
- 2 switches

For the battery holder I used my own version which you can find here:
http://lucstechblog.blogspot.com/2016/04/3d-printed-battery-holder-i-was.html

In the final version I attached a switch to the VCC power line. That made it possible to switch between battery power and an USB power bank.



The switches are attached to GND and the I/O pins.
The DAC-L and DAC-R outputs arae attached to a headphone or to an amplified speaker or to an input on your home stereo set.





The above picture shows you my real-world test setup. I have used this with simple head-phones, an USB powered speaker and attached it to my stereo set.

I was impressed by the overall sound quality. It was much better as I expected from such a cheap module.

Flaws.

well yes there are a few problems / flaws.

Watch the cabling.
By using leads that are too long there is noise being picked up. This will disappear at higher volumes but is annoying at low volumes. Strange is that it did not occur all the times. Whyen skipping through the songs on the SD card the noise seemed to disappear. However best practice is to keep the lines short to avoid the noice alltogether.

No continuity
The MP3 player stops playing after each song. You will have to press the next or previous button for playing another song.

Solutions

For the noise the solution is simple: keep the leads as short as possible.

For the continuity the solution is obvious: use an Arduino or ESP to control the module. That's something that is coming up in another story.

Till then,
have fun

Luc

Friday, May 3, 2019

Dweet: A volatile IOT cloud service

For an index to all my stories click this line

In a previous story which you can read here I wrote about Thingspeak. Thingspeak is a service where you send (sensor) data which is then displayed on a webpage. The advantage of this is that you can check your data from anywhere in the world. This way you do not have to open a port on your router to get to your data which may present some vulnerability.

Dweet is a similar service only with a twist.



The name Dweet is derived from Twitter where you tweet messages. Dweet is Data tWEETing. You can send as many data sets to dweet as you like but only the last five are stored for 24 hour. Next to that Dweet does not offer a website where you can check your data. Data has to be retrieved by an API call and is send back in JSON format. You even do not have to make an account on the Dweet service. You just Dweet your data and that's that.

Sounds complicated ??? Well it is not. Read on.

So why should you use Dweet.

First you do not have to make an account or anything. You can use the service without logging in or any other means of identifying yourself. So Dweeting is pretty anonymous. Next you can send as many Dweets as you like. A Dweet can contain up to 2000 characters. So thats an awfull lot of sensor data you can send. Besides that you can have multiple microcontrollers each sending Dweets under a different name. All those Dweets can be retrieved by one or more different microcontrollers even by multiple users.

I presume this all sounds hazy. So let's start with some examples that make everything clear for you.

Let's start !

Suppose you have a sensor reading that you want to share. For simplicity's sake let's say it is a temperature value of 25.

Dweet is meant to be used for the IOT (Internet Of Things). So to distinguish your Dweet amongst the thousands of other Dweets send every minute, think up for an unique name for your Thing. Keep it simple so you can remember it easily. For example. My name is Luc I, I want to Dweet the temperature and it is 2018. Lets call my Thing: Lucstemp2018

Now we have a name (Lucstemp2018) and an example sensorvalue (25). Let's Dweet that.

The Dweet.io home pages tells us to dweet you simply have to call an URL like:

https://dweet.io/dweet/for/my-thing-name?hello=world

In our example that would be:

https://dweet.io/dweet/for/Lucstemp2018?temp=25

Just put that in your Browser and you will get the following message back:


 
As you can see the Dweet has succeeded, the name of our Thing is Lucstemp2018 and the data what we are looking for is called temp and the value is 25.

Let's see if we can retrieve the information. For retrieving we use again an API call. The home page tells us again the general format which is:

https://dweet.io/get/latest/dweet/for/my-thing-name

That's easy to implement for our example. The Api Call should be:

https://dweet.io/get/latest/dweet/for/Lucstemp2018

Again put this in your browser and you will get the following result:



So we succeeded retrieving the data. The Thing name is the same and the data is 25.

ERROR !!!!



If something in the name is wrong or you are trying to retrieve data that was send more as 24 hours ago you will get an error message looking like the above picture.

Sending and retrieving multiple data.

Suppose you want to send multiple data. For example not only the temperature but also a notification if a door is open, a window is open and if a light switch is on or off.

Well that is easy. You just add multiple data by combining them with the & sign.

Lets try with the temperature and the indication of a light switch. We send a 1 if the switch is on and a 0 if the switch is off.
You could send the words ON and OFF however I will combine Dweet in the future with another service called Freeboard and for that purpose it is easy to represent on with 1 and off with 0.

Here is the Dweet, put it again in your browser:

https://dweet.io/dweet/for/Lucstemp2018?temp=18&switch=1



And here is the confirmation that we succeeded. As you can see two variables have been saved being temp and switch.

Lets see if we can retrieve that. The command for retrieving is the same one we used before:

https://dweet.io/get/latest/dweet/for/Lucstemp2018



There it is: we have retrieved the data.

Remember that I told you that a Dweet can contain up to 2000 characters. Therefore you can not only send sensor data but also complete texts. An example could be:

https://dweet.io/dweet/for/Mymessage?text=This is an example of what can be send with Dweet


And bingo, this worked. Without any hassle we created a new Thing which is called Mymessage and the variable is called text. This does not erease or interfere with the previous thing which still exists (as long as there have not waited 24 hours)

To retrieve the text you use the next call:

https://dweet.io/get/latest/dweet/for/Mymessage



And this is the result.



In case you are wondering...........
YES this story was written on 17 November 2017 at almost 1 o'clock in the night.

The purpose of all this.

So what's the purpose of this. What can we do with it.

Suppose you are at work and want your loved ones at home to know that you are on your way home. This can be done by having an ESP8266 at your work sending a Dweet and at home an ESP can be polling the latest Dweets so they know when you are coming home. As you might have seen in the previous examples Dweet automatically adds the date and time to a Dweet. So your loved ones even know when you have left work.

Let's look at another example.
Attach at holliday cottage a door or drawer sensor to an ESP and let it Dweet when the door or drawer is opened. An ESP at home can then check for Dweets and see if the door/drawer were opened and blink a light or give an audible signal or even send a message to your Phone.

"Hoho" is what I can here you think. The examples show how to Dweet from your browser. But your talking about Dweeting with an ESP.  So let's do that.

Dweeting from a program.

We can do this the hard way (the C++ way) or the easy way. Well I am lazy so let's take the easy way. Let's use my favorite devellopment tool: ESPBasic.

I am using ESPBasic here as it is (in my humble opinion) THE most easy developping environment for the ESP series. You can read a detailed instruction on how to install ESPBasic and take the first steps here: http://lucstechblog.blogspot.nl/2017/03/back-to-basic-basic-language-on-esp8266.html





' =================================================
' Dweet for Luc's weblog
' First send a fake temperature and switch
' =================================================

tosend$ = "dweet.io/dweet/for/Lucstemp2018?temp=18&switch=1"
print wget(tosend$,80)
delay 2000

' =========================================
' now lets see if we can retrieve the Dweet
' =========================================

request$ = wget("dweet.io/get/latest/dweet/for/Lucstemp2018",80)
print request$

You can see there isn't much to it.

The sending part.

tosend$ = "dweet.io/dweet/for/Lucstemp2018?temp=18&switch=1"

First we make a string containing the api call.

print wget(tosend$,80)

Next print wget sends it onto the internet.

The retrieving part.

request$ = wget("dweet.io/get/latest/dweet/for/Lucstemp2018",80)
print request$

Just as simple as the sending part.

Suppose you want to distill the temperature out of the answer that is returned.

reqfound$ = JSON(request$, "temp")
print reqfound$

Takes care of it all.
The JSON parser distills the value of the temp variable for you.

Here is the complete code that first sends a Dweet, then waits 2 seconds and then retrieves it after which the required data is distilled:



' =================================================
' Dweet for Luc's weblog
' First send a fake temperature and switch
' =================================================
wprint "<br>"
wprint "Sending the Dweet<br>" wprint "=================<br>" tosend$ = "dweet.io/dweet/for/Lucstemp2018?temp=18&switch=1" wprint wget(tosend$,80)
wprint "<br><br>"
delay 2000 ' ========================================= ' now lets see if we can retrieve the Dweet ' ========================================= wprint "Receiving the Dweet<br>" wprint "===================<br>" request$ = wget("dweet.io/get/latest/dweet/for/Lucstemp2018",80) wprint request$
wprint "<br><br>"
' ========================================= ' now lets see if we can retrieve the Dweet ' ========================================= wprint "The temperature is<br>" wprint "==================<br>" reqfound$ = JSON(request$, "temp")

This is how it looks in the output window:




There's more

Just go to Dweet's home page and you will find a few more API calls which you can use. There is also a paid service that makes it possible to save the Dweets for a month. You can find the homepage here: https://dweet.io/

Ok guys and girls.
Time for you to do some experiments.
Play with this and wait for the next installment.

Have fun

Luc Volders

Friday, April 26, 2019

Unlimited output ports for your Micro:bit

For an index of all my stories click this text

WS2811 as output for micro controllers part III

In the first part I showed you how to use WS2811 chips to create an almost unlimited number of PWM controlled outputs for an ESP8266.

The WS2811's are the chips that are build into the so called Neopixels. More detailed basic information about Neopixels can be found here: http://lucstechblog.blogspot.nl/2015/10/neopixels-ws2812-intro.html

So a Neopixel is basically a WS2811 and 3 leds build as a single chip. I am using just the WS2811's. As these can control 3 leds we should be able to use them as 3 outputs for a microcontroller. By daisy chaining them (just like we do with Neopixels) we can create an infinite number of outputs for any microcontroller. I did this succesfully with an ESP using LUA and Basic in Part 1 of this series. Read that story here http://lucstechblog.blogspot.com/2019/04/unlimited-outputs-for-your_12.html

Part II described how to use this technique with an Arduino and an Attiny85. Read that story here: http://lucstechblog.blogspot.com/2019/04/unlimited-outputs-for-your.html

And in this part I am going to show you how it is done with a Micro:bit.
For this I presume you have basic electronics knowledge because we are going to use the same hardware setup as we did with the Attiny85.

Hardware

As said above use the same hardware setup as used with the Attiny85.




In this setup replace the Attiny85 with the Micro:bit.




Power the Micro:bit independently from the WS2811's. The WS2811's work best at 5 volts and the Micro:bit works at 3 volts. So attach the GND from the Micro:bit to the Ground rail on the breadboard and attach the data line to P0. Forget about the 5Volt power line and supply the Micro:bit with it's own power supply.


Fortunately the WS2811's (just like the Neopixels) accept data at 3 volt level.




Here is the real-world setup.

Software.

The software is written in blocks.
I presume you are familiar with the Micro:bit programming environment; You can find the editor here: https://makecode.microbit.org/

Here is the full code:









The first block is always run when the Micro:bit is started. It displays a welcome message and attaches the neo driver to P0 and tells it that we are going to use 2 leds (WS-2811's)

The second block is just a counter that counts from 1 to 6 everytime the A button is pressed.

The third block is where the magic happens.
If you press the B button the block checks what number the counter was set at with button A in the previous block.
If the counter is set from 0 to 2 the first WS2811 is adressed. When the counter has a value from 3 to 5 the second WS2811 is adressed. The actual value determines which output then is activated.

So what happens is that you choose a number by repeatedly pressing the A button and activate the choosen output by pressing B.

That's all folks.



For clarity I show you here the underlying Javascript code.

Python

Next to programming in Blocks there is Python which has a loads more possibillities but is intended for the more experienced programmers.



The Python code almost speaks for itself.
First the libraries are imported. Then the WS-2811's are initialised on P0 (pin0)
Next step is a loop that sets the values of the output ports at a random PWM value so all led's will independently be dimmed at different values.

That's it.

I bet you can start all kinds of projects with this technique. This is not only good for attaching numerous leds to your Micro:bit. Attach transistors to each output and you can control multiple motors or ledstrips. As always: use your imagination and have fun.

Till next time

Luc Volders

Friday, April 19, 2019

Unlimited outputs for your microcontroller part II

For an index to all my stories click this line

In the previous part I showed you how to use WS2811 chips to create an almost unlimited number of PWM controlled outputs for an ESP8266. You can find that story here: http://lucstechblog.blogspot.com/2019/04/unlimited-outputs-for-your_12.html

The WS2811's are the chips that are build into the so called Neopixels. More detailed basic information about Neopixels can be found here: http://lucstechblog.blogspot.nl/2015/10/neopixels-ws2812-intro.html

So a Neopixel is basically a WS2811 and 3 leds build as a single chip. I am using just the WS2811's. As these can control 3 leds we should be able to use them as 3 outputs for a microcontroller. By daisy chaining them (just like we do with Neopixels) we can create an infinite number of outputs for any microcontroller. I did this succesfully with an ESP using LUA and Basic in Part 1 of this series.

Now let's see if we can use this technique also with an Arduino or an Attiny85.


Oh and by the way, with a little modification (mainly altering the pin number) you can use this also for the ESP8266 and ESP32 in Arduino language.

As both the Arduino and the Attiny85 have no Wifi capability it is more difficult to control them from the outside world. Control has to be taken care off with potentio meters or sensors. In the examples I am going to show here there is no outside control. The programs will control everything. For demo purposes this is sufficient and I am sure you find ways to incorporate this in your own projects.

Breadboard setup




As you can see the setup is almost the same as in the previous story. I attached the Arduino's ground and +5Volt to the ground and power rails of the rest of the circuit to power the complete setup. The Arduino's pin 6 is used to control the WS2811's through a 470 OHM resistor.
It is the same setup you would use to attach a bunch of Neopixels to your Arduino. As long as you use just a few WS2811's and leds youn can power the setup from your Arduino.

When you are going to attach more WS2811's use the seperate USB power supply for the WS2811's like discussed in part 1 in this series.


The Arduino program

The program is written in C++ the standard programming environment for the Arduino. Lets look at the code:



// WS2811 Test by Luc Volders
// This program sets multiple leds on and off in a sequence

#include <Adafruit_NeoPixel.h>
#include <avr/power.h>

// Which pin on the Arduino is connected to the NeoPixels?
#define PIN            6

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      2

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 500; // delay for half a second

void setup() 
{
  pixels.begin(); // This initializes the NeoPixel library.
}

void loop() 
{
    pixels.setPixelColor(0, pixels.Color(00,0255,255)); 
    pixels.setPixelColor(1, pixels.Color(00,0255,255));
    pixels.show(); 
    delay(delayval); 
    pixels.setPixelColor(0, pixels.Color(0255,0,0));
    pixels.setPixelColor(1, pixels.Color(0255,0,0));
    pixels.show();
    delay(delayval); 
}


The first thing the code does is to import Adafruit's Neopixel library. If you do not already have installed this library you will find a description on how to do that here:
https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library-installation

Next step is that we tell the program that the WS2811's are attached to pin 6. I/O port no 6 on the Arduino is a PWM port and that is what we need to control the WS2811's.

Then we define the number of WS2811's which is 2 in this case. These 2 WS2811's will give us 6 output ports.

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

This line does the actual setup for the WS2811's.
NUMPIXELS is the amount of WS2811's, PIN is on which IO port they are attached, NEO_GRB tells the library that it must use GRB instead of RGB and NEO_KHZ800 tells it the frequency with wthat the WS2811's should be controlled.

Let's look at the main loop:

pixels.setPixelColor(0, pixels.Color(00,0255,255));

The first zero is the number of the WS2811 in the line. The last 3 numbers are the PWM values we are going to send to the individual outputs of that WS2811. So in this line we set the first led OFF and the second and third led ON.

After the delay we turn that around:

pixels.setPixelColor(0, pixels.Color(0255,0,0));

This sets the first led ON and the other two OFF.

Altering the value 255 in any figure between 0 and 255 will DIM the led in stead of setting it to full brightness.

And here are the real life results:





So this works flawlessly. With 2 WS2811's I have created 6 extra outputs for the Arduino.

On to the Attiny85

We can use this technique also with an Attiny85. The Attiny85 normally just has 5 output pins. It would give our projects an enormous advantage if we could expand this to many more PWM able outputs. Well here we go.

Breadboard setup:



As you can see the breadboard setup is again almost identical to the previous setups.
In this case you need to use the USB external power supply.

As usual the WS2811's are attached through a 470 Ohm resistor to I/O port 1 of the Attiny85.


And this is what it looks like in real life.

The program


// Attiny85 code for controlling 6 output with ws2811
// Code written by Luc Volders

#include <Adafruit_NeoPixel.h>

// Which pin on the Attiny85 is connected to the NeoPixels?
#define PIN            1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      2

// Setup the NeoPixel library with how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int toets1=0;

void setup() 
{
  pixels.begin(); // This initializes the NeoPixel library.
  for(int i=0;i<NUMPIXELS;i++)
  pixels.setPixelColor(i, 0,0,0);
  pixels.show();
}

void loop() 
{
  for(int i=0; i<255; i++)
  {
  pixels.setPixelColor(0, 255-i,i,i);
  pixels.setPixelColor(1, 255-i,i,i);
  pixels.show();
  delay (10);
  }
}


I just altered the Arduino program a bit. The program is going to fade the leds in and out. This is done in the main loop.

The first leds are going to fade from bright to OFF and the other leds are fading from OFF to full bright.


 

And here is the result. Six extra (PWM) outputs for an Attiny85 !!!!

The next part is going to show you how we can use this technique for expanding the BBC's Micro:Bit output ports.

Till next time.
Have fun

Luc Volders

Friday, April 12, 2019

Unlimited outputs for your microcontroller

For an index to all my stories click this text

Sometimes I have these strange / stupid / twisted ideas let me explain.

While thinking about a project I realised I would need a controller with many outputs. Let's first look at the options.

- An ESP-01 has 2 I/O ports and with a trick you can use 4.
- A NodeMCU has 11 I/O ports.
- An Attiny 85 has 5 I/O ports.
- An Arduino Uno has 19 ports.
- An Arduino Mega has 53 ports

The Arduino Mega would have been an option however it lacks Wifi.
I could use a NodeMCU with several 74HC595 shift registers which each would give me 8 ports. For 50 output ports I would need 7 of these which would make programming a complicated matter.

I then had a twisted Idea.

Look at the Neopixels. I can attach a whole bunch of Neopixels to any of the above mentioned controllers and set each led to any RGB color individually. If you want to know more about these small wonders read this story:
http://lucstechblog.blogspot.nl/2015/10/neopixels-ws2812-intro.html

Neopixels contain 3 leds and a controller chip in one casing. That controller chip is the WS2811.

The WS2811 can be daisy-chained almost endlessly and each of these chips has 3 output ports. Well, well. If these chips could be bought without the led's, that would make an almost endless supply of output ports for any controller. And they would be easy programmable. 


And best of all: Not only would they be able to set a led on or off, they would be able to use PWM to dim the leds, or control the speed of a motor, or control multiple ledstrips !!!

Tell me. Isn't that a strange / stupid / twisted idea ???

The WS2811 chips

Let me start with some general information.

A search on the website of my favorite Chinese supplier immediately showed that the WS2811 chips indeed can be bought without leds. So I immediately ordered a few. I got 10 pieces for about 3 euro but they are even cheaper now. For economics sake this boils down to (in my case) 10 cents for every extra output on your Microcontroller.





Mine where shipped as a strip of 5 pieces. They were not interconnected so there is soldering involved.




Each individual PCB on which the WS2811's are soldered is 15 x 15 mm.




 This picture clearly shows you the size of the PCB's compared to an ESP01.

As the WS2811's are put on individual PCB's you could break the strips up and put them apart if you needed more adressable outputs over a larger distance. Adafruit advises a maximum distance of about 1 meter between each WS2812 neopixel. However I read on a forum that someone had good results with WS2812's which were 6 meter apart.
All depends on the quality of the soldering, the used wires and the power supply. So testing is required  !!!!

Please be aware that the WS2811's have a common Anode.
Normally you will attach a led to a signal and to the GND. This is the other way round. The led is attached to an I/O port which must provide the GND and the other side is attached to the +5V. Don't forget the delimiting resistor.
We will see more of this later on.

You should wire the WS2811's the same as you would wire Neopixels. Attach a large capacitor (1000 microfahrad at 6.3 volts or higher) across the GND and + of the power supply. And connect a 300-500 ohm resistor between the pin of your microcontroller and the first Neopixel in line.

Soldering

As you can see the individual PCB's have a GND and 5V connection on either side so the can easily be daisy-chained. On one side is the DI (data-in) connection and on the other side the DO (data-out) connection. The DI of the first in line will be connected to your Micro Controller and the DO can be connected to the next DI. The same as you would do with Neopixels.

At the center of the PCB are 4 connections. R G B and +. Normally the LED's will be soldered here. That would be RGB leds with a common Anode (+).

I started with wiring the connections to the first PCB. I sacrified some Dupont wires for this experiment. This made it easy to connect the WS2811's to a breadboard.


Next I interconnected 2 PCB's by soldering small pieces of wire between them.


And the last step, was to solder wires to the RGB connections. For clarity I used red, green and blue wires.

First test

Just be patient and keep reading this web-log. Because in the next part I am going to show you how to use the WS2811's with an Arduino and an Attiny85 programmed in C++ and even with a BBC Microbit programmed both in Python and in Java. Best part Is that I am going to show you how to attach and control 2 ledstrips at the same time !!!

However for all my rapid testing and fast devellopment I use ESPBasic.  As all programming an testing is done in a web-browser it is the fastest way to test anything on an ESP. Read a tutorial on ESP-Basic here: http://lucstechblog.blogspot.nl/2017/03/back-to-basic-basic-language-on-esp8266.html

First look at the breadboard setup


And this is how it looks in real life. As you can see I have soldered wires to 2 of the WS2811's and attached leds with a delimiting resistor.

Further you can see there are two USB cables. The first one (the pink one) powers the Wemos D1 (NodeMCU) and the second one (the green one) powers the WS2811's. You can not feed all of this from your Wemos D1 or NodeMCU module. Thats why I attached two separate power supplies, both an ordinary 5Volt phone charger from the dollar shop.

Attach a multimeter across the blue connection of the first WS2811 and GND.

And use the following program:


neo(0,0,0,0)

wprint |<h1 style="text-align:center;">Luc Volders</br>WS2811 Relay|
wprint "<br/><br/>"

button "<h3>Relay on</h3>",[relon]
button "<h3>Relay off</h3>",[reloff]

wait

[relon]
neo(0,0,0,255)
wait

[reloff]
neo(0,0,0,0)
wait

That's all


That small program looks like this on the screen of your computer / phone /tablet

Pressing the Relay-on button will give you 0 Volts and pressing the Relay off button will give you something like 0.9 volt. That brings us nowhere.

Now attach one end of the multimeter to +5V in stead of the GND and you will measure -5.22 volts when you press Relay-on and 0 volts when you press relay off. And that's what we need.

Like stated above the WS2811 have a common anode so the GND comes from the R,G,B side.

Attach a led with a 220 ohm resistor, and to make it go on and off, attach the Anode side of the led to +5 volt and the cathode side to the B wire of the first WS2811. Just press the button on the web-page to switch the led on and off.

As a side-note: Guess you know now why I use ESP-Basic so often as my favorite devellopment system. In just a few lines of code I have made a web-page with a button and control some WS-2811's

Next step is attaching a Relay.
This is easier. Just attach the power lines and attach the control line to the Blue line of the first WS2811.
Pressing the Relay on or Relay Off button will switch the realay accordingly on or off.
Modern relay modules have a common connection in the middle and a connection that closes when a GND signal is supplied and one that closes when a + signal is supplied.




So in this case the upper connection and the middle connection are closed when the button is not pressed and the value send to the WS2811 is 0. If a 1 (5volt) is send the middle connector is connected to the lower connector.

Something more complex.

I had 6 leds attached to the output lines of 2 WS2811's.

 
In order to test this setup I wrote a program in LUA.

 
The program builds a webpage and puts 12 buttons on it. Each led has 2 buttons: one for ON and one for OFF.

wifi.setmode(wifi.STATION)
wifi.sta.config("XXXXXXXX","YYYYYYY")
ws2812.writergb(3, string.char(0,255,0,0,255,0,0,255,0))
print(wifi.sta.getip())
led1 = 0
led2 = 0
led3 = 0
led4 = 0
led5 = 0
led6 = 0
tmr.delay(2000000)
ws2812.writergb(3, string.char(0,255,0,0,255,0,0,255,0))
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive", function(client,request)
        local buf = "";
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if(method == nil)then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local _GET = {}
        if (vars ~= nil)then
            for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
                _GET[k] = v
            end
        end
        buf = buf.."<h1>WS2811 Web Server</h1>";
        buf = buf.."<h1>Made By Luc Volders</h1>";
        buf = buf.."<p>Switch 1 <a href=\"?pin=ON1\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF1\"><button>OFF</button></a></p>";
        buf = buf.."<p>Switch 2 <a href=\"?pin=ON2\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF2\"><button>OFF</button></a></p>";
        buf = buf.."<p>Switch 3 <a href=\"?pin=ON3\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF3\"><button>OFF</button></a></p>";
        buf = buf.."<p>Switch 4 <a href=\"?pin=ON4\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF4\"><button>OFF</button></a></p>";
        buf = buf.."<p>Switch 5 <a href=\"?pin=ON5\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF5\"><button>OFF</button></a></p>";
        buf = buf.."<p>Switch 6 <a href=\"?pin=ON6\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF6\"><button>OFF</button></a></p>";              
        local _on,_off = "",""
        if(_GET.pin == "ON1")then
              led1 = 255
              ws2812.writergb(3, string.char(led1,led2,led3,led4,led5,led6))
        elseif(_GET.pin == "OFF1")then
              led1 = 0
        elseif(_GET.pin == "ON2")then
              led2 = 255
        elseif(_GET.pin == "OFF2")then
              led2 = 0
        elseif(_GET.pin == "ON3")then
              led3 = 255
        elseif(_GET.pin == "OFF3")then
              led3 = 0
        elseif(_GET.pin == "ON4")then
              led4 = 255
        elseif(_GET.pin == "OFF4")then
              led4 = 0  
        elseif(_GET.pin == "ON5")then
              led5 = 255
        elseif(_GET.pin == "OFF5")then 
              led5 = 0
        elseif(_GET.pin == "ON6")then
              led6 = 255
        elseif(_GET.pin == "OFF6")then 
              led6 = 0          
        end
        ws2812.writergb(3, string.char(led1,led2,led3,led4,led5,led6))
        client:send(buf);
        client:close();
        collectgarbage();
    end)
end)

As you can see there is a lot more code involved to build a webpage with some buttons on in LUA.

A little explanation.

wifi.sta.config("XXXXXXXX","YYYYYYY")

Fill in your own routers credentials.

Next a network connection is established.

buf = buf.."<p>Switch 1 <a href=\"?pin=ON1\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF1\"><button>OFF</button></a></p>";

These lines put the name "Switch x"on the webpage and put two buttons after the name being ON and OFF and they will get connected to the variables ON1 and OFF1

        if(_GET.pin == "ON1")then
              led1 = 255
              ws2812.writergb(3, string.char(led1,led2,led3,led4,led5,led6))
        elseif(_GET.pin == "OFF1")then
              led1 = 0

In these lines is tested wether the button is pressed and the accompanying led is set ON of OFF by setting the variable led1 to 255 or 0. This is done for all 6 leds.

        ws2812.writergb(3, string.char(led1,led2,led3,led4,led5,led6))

The WS2811 DATA IN line is connected to D3 on the NodeMCU and the led's are set according the value that is in the varaibles led1 through led6


As you can see in the picture I replaced a led with a relay for testing and it worked just fine.

Even more complex

The next step was to write a program that produced a webpage with sliders which would set the intensity of the leds. I did that in Basic as I have (until now) no clue on how to put sliders easily on a webpage with Lua or C++ code.


The first program was very simple and had no fancy layout.

neo.setup(d8)
timer 100, [change]

rgbval1=0
rgbval2=0
rgbval3=0
rgbval4=0
rgbval5=0
rgbval6=0

slider rgbval1, 0, 255
wprint "<br>"
wprint "<br>"

slider rgbval2, 0, 255
wprint "<br>"
wprint "<br>"

slider rgbval3, 0, 255
wprint "<br>"
wprint "<br>"

slider rgbval4, 0, 255
wprint "<br>"
wprint "<br>"

slider rgbval5, 0, 255
wprint "<br>"
wprint "<br>"

slider rgbval6, 0, 255
wprint "<br>"
wprint "<br>"

wait

[change]

neo(0,rgbval1,rgbval2,rgbval3)
neo(1,rgbval4,rgbval5,rgbval6)

wait

The code was equally simple.

De first WS28-11's Data-In line is connected to D8 on the NodeMCU. Then a timer is initiated that every 100 ms calls the routine [change]. In this routine the value of the sliders is send to the WS2811's which alter the intensity of the leds accordingly.


I wanted it to look a bit more fancy and that resulted in the above picture. Besides having a better looking web-page I decided to alter the last slider in an on-off button and like before I attached a relay in stead of the last led.


wprint "<!DOCTYPE html>" 
wprint "<html>"
wprint "<head>"
wprint "<style>"
wprint "h1 {text-align:center;}"
wprint "</style>"
wprint "</head>"
wprint "<body>"
wprint |<body style="background-color:Burlywood  ;">|
wprint |<H1><span style="color: Dodgerblue;">|
wprint "WS2811 Control"
wprint "<br>"
wprint "</H1>"

neo.setup(d8)
timer 100, [change]

ws0102=0
ws0102=0
ws0103=0
ws0201=0
ws0202=0
ws0203=0

wprint "Control 1"
slider ws0101, 0, 255
wprint "<br>"
wprint "<br>"

wprint "Control 2"
slider ws0102, 0, 255
wprint "<br>"
wprint "<br>"

wprint "Control 3"
slider ws0103, 0, 255
wprint "<br>"
wprint "<br>"

wprint "Control 4"
slider ws0201, 0, 255
wprint "<br>"
wprint "<br>"

wprint "Control 5"
slider ws0202, 0, 255
wprint "<br>"
wprint "<br>"

'wprint "Control 6"
'slider ws0203, 0, 255
'wprint "<br>"
'wprint "<br>"

button "Lamp 01 ON", [lamp01on]
a = "background-color:Gainsboro;"
a = a & "border: 3px solid black;"
a = a & "font-size: 22px;"
a = a & "font-weight: bold;"
a = a & "color: fuchsia ;"
a = a & "border-radius: 12px;"
cssid htmlid(), a

button "Lamp 01 OFF", [lamp01off]
a = "background-color:Gainsboro;"
a = a & "border: 3px solid black;"
a = a & "font-size: 22px;"
a = a & "font-weight: bold;"
a = a & "color: fuchsia ;"
a = a & "border-radius: 12px;"
cssid htmlid(), a

wait

[change]

neo(0,ws0102,ws0101,ws0103)
neo(1,ws0202,ws0201,ws0203)

wait

[lamp01on]
ws0203 = 255
neo(1,ws0202,ws0201,ws0203)
wait

[lamp01off]
ws0203=0
neo(1,ws0202,ws0201,ws0203)
wait

Again the code speaks for itself and you can see how easy it is to build something fantastic in just a few lines with Basic.

This gives you enough to play with for a short time. Story number 2 coming up soon and like I said before that will show you how to use this with an Arduino (attiny85) and even a BBC Microbit. And I'll show you how to control multiple RGB led strips simultaneous using this method.

So till next time.
Have fun !!!

Luc Volders