Showing posts with label Neopixels. Show all posts
Showing posts with label Neopixels. Show all posts

Friday, March 28, 2025

Print your own USB connector

For an index to all my stories click this text.

Sometimes I find something on the web that is so usefull that I want to share it with you.

Powering your circuits.

When testing and building a small circuit with just one or two sensors you can use the power that your microcontroller supplies over it's 5V pin. Both the ESP32 and the Raspberry Pi Pico have a 5V and 3V3 power out pin.

But when I need more power I use an USB breadboard connector to power the project.


An example is this circuit where two TM1637 7 segment displays are connected to a Raspberry Pi Pico. The Raspberry pi pico is powered through it's USB port and on the left-top side you can see a breadboard USB connector attached to a USB power plug.

Nothing wrong with this but I always seem to run out of breadboard USB connectors.

3D printer to the rescue

Then I found this on the web:
https://www.instructables.com/Minimalist-USB-Connector-No-Special-Hardware-Requi/


This is a 3D printed USB connector. The photo shows the assembled version.
But does it work ????


Works like a charm !!!
As you can see the USB connector is plugged into a powerbank and the multimeter shows that a nice 5V is supplied.

The STL files

The connector consists of 2 parts.

You can find the STL files in the original story which you can find here:
https://www.instructables.com/Minimalist-USB-Connector-No-Special-Hardware-Requi/


The first part is the bottom in which you need to insert the wires. The second part is the top which you should glue and press on to the bottom part when the wires are placed. The top part has ridges that help keep the wires in place.


This is how the files look in my slicer. I use Cura.


Set the quality at 0.2mm and supports on. As these are small parts you could set adhesion also on.

Assembling

I used solid copper wire with a diameter of 0.5mm. That worked very well.

I took a slightly different approach to assembling as what the original developer described.

First I stripped the wires.


Then I pulled the stripped part through the holes.

Then I glued the lid on.
The last step was to cut off the excess wire.

The blue wire at the top is GND.
The red wire at the bottom is VCC (5V).
Please test before you actually put it to use to make sure the wires are not twisted. If you mix the wires up you might/will blow up your circuit so test, test, test !!!


The wires are thick enough to fit direct into a breadboard.

You can make the wires any length you want. Short to connect to a powerbank and fit on your desk. Or make them long to connect to a wall outlet with an USB power plug.

I have printed several of these. They are ready to use in my drawer. A really great design.

Til next time
Have fun

Luc Volders

Saturday, December 7, 2024

Order your Christmas presents now !!

For an index to all my stories click this text

Now is the time !!

Just a shameless plug.

IF you have any friends, loved ones or relatives that are stepping into the wonderful world of Microcontrollers, electronics or the Internet Of Things please consider buying one of my books. And now is the time so it will arrive in time before Christmas

And by ordering these books you also support this weblog which allows me to buy new sensors etc. to build new projects and write about them.

These books are aimed at beginners to this hobby and are clearly written with many examples and projects that get you started right away.


This book was written several years ago and is still a bestseller.
It explains working with a breadboard, the C++ (Arduino) language and explains the workings of many sensors. Next to that the book shows how to work with cloud based services. It also shows how to build a simple webserver that allows to get sensor (like your home temperature etc) data from anywhere in the world.
Click here to buy this book.


The Raspberry Pi Pico was the first microcontroller from the Raspberry Pi Org. that is well known for its small Linux computers. The Pico took the IOT world by storm because of it's low price, worldwide availability, many IO pins, great speed and the availability of the MicroPython language that makes programming this chip really easy. This book shows how to install MicroPython, and covers the basic syntax of this easy to learn language. Next to that the book shows how to work with all kinds of sensors, motor, buttons etc. etc. All projects are well documented and breadboard based so no soldering !! The projects in this book will also work on the Pico2.
Click here to buy this book.


The Raspberry Pi Pico W is the successor of the Pico and adds Wifi to its capabilities. The book shows how to install the MicroPython language and the basic syntax. Then it focus on working with many sensors, motors, buttons etc. The book shows how to use wifi to get access to internet services. And a lot of attention is paid to building webservers in MicroPythoin that allow you to read sensors (like your home temperature) and set lights on or off from anywhere in the world. The projects in this book will also work on the Pico 2W
Click here to buy this book.


Javascript is without a doubt the most used computer language in the world. Anytime you click a button on a webpage or see some interactive action on a webpage Javascript is involved.
This book does not learn how to program in Javascript but gives you hundreds of tips while programming in this language. It covers topics like sorting of data, date manipulation like calculating the number of days between days, rounding figures, hding and showing hidden elements on a webpage, acting on key presses etc. etc. etc. There are hundreds of tips covering almost any aspect of building interactive webpages and working with the data on these pages.
This book might also be a valuable asset when building webservers with microcontrollers like the ESP32 and Raspberry Pi Pico series.
Click here to buy this book

Have a good Christmas
and have fun

Luc Volders

Friday, December 9, 2022

Last post of 2022

For an index to all my stories click this text.

The holliday season is coming up. Lots of time to celebrate with your loved ones and friends, but also lots of time to spend with your hobby. And maybe you have relatives or friends also want to start with electronics or the Internet Of Things. What better way than a book that explains it all in an easy to understand manner.

Next to being the author of this blog I also wrote (until now) 3 books in plain English and one in Dutch that explain these things in an easy way. That is why the series is called xxxx Simplified.

Raspberry Pico W Simplified.



This is my latest book and was released in October this year.
The book covers the already very popular Raspberry Pi Pico W. In which the W stands for Wifi. The Raspberry Pi Pico W is a serious competitor to the famous ESP32. Not only has this board a lot of memory, a fast dual-core processor, loads of IO ports and USB for easy programming. It also has Wifi which makes it ideal for the Internet of Things. Look at it as an Arduino with added Wifi.

This book covers the following subjects:
Installing MicroPython, the MicroPython language, the pins layout, how to use a breadboard, adding power, how to use a button, how to use leds, fading leds with PWM, connecting to wifi, check if someone is at home with ping, Dallas DS18B20 thermometer chip, building your own MicroPython library, access internet data with Urequests, getting jokes from the internet, publishing to and retrieving data from Thingspeak, using an LDR for measuring light intensity, using mains power with a relay, movement detection with a PIR, getting notifications on your phone with Pushbullet, vibration detection, sending data to Telegram Messenger, how to use JSON, sending data to and retrieving data from Dweet, building a webserver that displays data and has buttons to control leds and lamps etc., attach a reset button.

Every project is build on a breadboard. All programs in the book are written in MicroPython and fully documented in detail.

This book is available through my publisher and through Amazon

https://www.lulu.com/shop/luc-volders/raspberry-pico-w-simplified/paperback/product-ke8vz9.html?q=luc+volders&page=1&pageSize=4

https://www.amazon.com/Raspberry-Pico-Simplified-Luc-Volders/dp/1471032361/ref=sr_1_3?crid=1W8CKDJ1TDLOC&keywords=luc+volders&qid=1668207187&sprefix=%2Caps%2C357&sr=8-3


Raspberry Pi Pico Simplified


The Raspberry Pi Pico was the first microcontroller released by the Raspberry Foundation. Within a year 1.000.000 (yes 1 million) pieces were sold. The Pico is a serious competitor for the Arduino range of microcontrollers. It has a fast processor, loads of IO pins and can easily be programmed with MicroPython. This book focuses on the MicroPython language and on how to use a multitude of sensors with this microcontroller.

The book covers the following subjects:
Getting started, installing libaries, Pico's pins layout, introduction to using a breadboard, power, basic programming knowlegde, buttons, leds, fading leds with PWM, Dallas DS18B20 Digital Thermometer, using an LDR for measuring light intensity, potmeter, servo motor, more power, using mains power with a relay, touch sensor, controlling a motor, making sound with a buzzer, neopixels, H-Bridge for advanced motor control, movement detection with a PIR, motion detection with the RCWL-0156 Radar, measuring distance, tilt sensor, vibration detection, display your data, rotary encoder, oled display and how to build a reset button.

Every project is build on a breadboard. All programs in the book are written in MicroPython and fully documented in detail.

This book is available through my publisher and through Amazon:


https://www.lulu.com/en/en/shop/luc-volders/raspberry-pi-pico-simplified/paperback/product-znrgmy.html?page=1&pageSize=4

https://www.amazon.com/Raspberry-Pico-Simplified-Luc-Volders/dp/1329449533/ref=sr_1_3?dchild=1&keywords=raspberry+pi+pico+simplified&qid=1629483987&sr=8-3

ESP32 Simplified



When the ESP8266 was released it was a sensation. It was a microcontroller like an Arduino but then with Wifi. The ESP32 offers even more benefits. The ESP32 has many IO pins, a fast processor, a lot of memory, bluetooth and an USB port so you can easily program it. The popular Arduino language (which is C++) is vailable for it and that opens the gate to many libraries for sensors and access to web-services. The ESP32 is a popular widely used microcontroller and therefore this book is a valuable source of information for anyone who wants to start with electronics and the Internet of Things.

This book covers the following subjects:
Installing the Arduino IDE, ESP32 board install, using the IDE, using the library manager, using ZIP libraries, installing libraries manually, first use of libraries, ESP32 Pin layout, ESP32 on a breadboard, introduction to using a breadboard, power, USB Breadboard connector,batteries, external Power Supply, programming basics, how to attach a button, buttons or switches, led, fading leds with PWM, Dallas DS18B20 digital thermometer, using an LDR for measuring light intensity, potmeter, make a dimmer, servo Motor, building a web server, more power, using mains power with a relay, automatic night light, touch sensor, a touch sensitive lamp, plant watering system, IFTTT, neopixels, thermometer with led indication, roll the dice, H-Bridge for advanced motor control, movement detection with a PIR, motion detection with the RCWL-0156 Radar, vibration detection, tilt sensor, display data with the TM1637, oled display, Thingspeak a cloud basede IOT, sending thermometer values to Thingspeak.

Every example is build on a breadboard so no soldering is required. Every example has an accompanying program which is documented in detail.

This book is available through my publisher and through Amazon:


https://www.lulu.com/shop/luc-volders/esp32-simplified/paperback/product-5yr98e.html?page=1&pageSize=4



https://www.amazon.com/ESP32-Simplified-Control-your-internet/dp/171694211X/ref=sr_1_1?dchild=1&keywords=esp32+simplified&qid=1601666983&sr=8-1



ESP32 Uitgelegd

This is the Dutch version of ESP32 Simplified and was the first book I published. It is available through my publisher, electronic shops like Otronic and Bol.

https://www.boekenbestellen.nl/boek/esp32-uitgelegd/9789463456814

https://www.otronic.nl/a-61328375/esp32/boek-esp32-uitgelegd-door-luc-volders/

https://www.bol.com/nl/nl/p/esp32-uitgelegd/9200000116004013/?bltgh=hWzTXg8hh8H1i6DDTvFJNw.1_4.5.ProductImage



Thanks for reading.
Have a great Xmas, a happy and healthy new year and loads of fun.

Luc Volders

Friday, March 18, 2022

More buttons on fewer pins

For an index to all my stories click this text

I am working at at larger project in which I need an ESP8266 to send certain data over wifi depending on buttons being pressed. Nothing exiting you might think. However in one particular case I might needa lot of buttons.

The ESP8266 boards like a NodeMCU module or a Wemos D1 have about 11 digital I/O ports available. So I could attach a button to each I/O pin giving me 11 buttons. However that leaves no room for attaching other items like control-leds or a display.

It gets worse when you are working with really tiny controllers like the Attiny85. This micro-controller has, when normally used, just 5 I/O pins.

Let's have a look how the commercially available keyboards work.



As you can see they are build in a matrix layout. The 4 x 4 matrix has 4 rows and 4 columns. In the software you make sure that one of the rows is set to LOW, the rest to HIGH. This way you can test which column gets the LOW signal and that intersection is the key being pressed. If none of the columns gets a LOW signal the next row is set to LOW and the test starts over.

This works great however has some flaws for me. First the software makes the controller load high. You actively have to set each row in its turn LOW and the rest HIGH and then test which column gets the LOW signal. This will keep your controller pretty busy.

Next to that for 12 buttons you will need 7 I/O pins. For 16 buttons you will need 8 pins. This leaves little room for control leds although I could use neopixels for that which only take one I/O port. And this is no option for working with an Attiny85 with its mere 5 I/O pins.

I needed something better. So started thinking.

The binary system.

Let's look at the binary system. If I have one wire it can be HIGH or LOW. When using two wires there are already more possibilities:

LOW LOW
LOW HIGH
HIGH LOW
HIGH HIGH


So how do I put that to use. Lets attach switches to the 2 wires using this principle.




Look at the schematic. The two pull up resistors make sure that if no key is pressed both lines are HIGH. That is the HIGH-HIGH state.
There are three buttons.
The first button is connected to the first line, second button to the second and third button to both.
The idea is ok but it just does not work. If you press button one the ground will indeed be connected to the first line, but it will flow through the wire connected to button three. And as this button is connected to both wires, so ground will be connected to both wires.
We have to prevent that ground will be connected to two wires at the same time and that is easy.




Just put diodes on the wires connected to the buttons.
If you press button 1 ground will be connected to line 1. Ground wants to flow to button three but is prevented by the diode so can not flow back to line 2.

That is it. So with two lines we can use three switches.




Above you can see the breadboard setup. And best part: it really works.

The binary system with 3 wires

Using 3 wires we have the following posibillities:

LOW LOW LOW
LOW LOW HIGH
LOW HIGH LOW
LOW HIGH HIGH
HIGH LOW LOW
HIGH LOW HIGH
HIGH HIGH LOW
HIGH HIGH HIGH


Leaving the last one out because that is when no button is pressed, we have 7 posibillities. So 7 buttons with just 3 wires.

Lets look at the schematics again.


Not a lot different from our fist setup with only two wires.
Does it look familiar somewhere ???
Well if you are a faithfull reader of this blog you might recognise this from my stories on Charlieplexing. The hardware setup is not quite the same but it has some resemblance. You can re-read that story here:
https://lucstechblog.blogspot.com/2017/09/charlieplexing.html or search my index page for all the Charlieplexing stories: http://lucstechblog.blogspot.com/p/index-of-my-stories.html

Adding visual feedback

I wanted a visual feedback for testing purposes. For that I added a string of 7 neopixels. The reason is obvious: attaching a bunch of neopixels can be done with just 1 I/O pin. For those not familiar with the term: neopixels are adressable RGB leds officially called WS2812. For basic information on Neopixels re-read this story: http://lucstechblog.blogspot.com/2015/10/neopixels-ws2812-intro.html

The software.

Let's start with the software in Arduino IDE (C++).



#include <Adafruit_NeoPixel.h>
#define PIXEL_PIN D8 
#define PIXEL_COUNT 7
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
void setup() 
{
 pinMode(D5, INPUT);
 pinMode(D6, INPUT);
 pinMode(D7, INPUT);
 attachInterrupt(digitalPinToInterrupt(D5), buttonpress, FALLING);
 attachInterrupt(digitalPinToInterrupt(D6), buttonpress, FALLING);
 attachInterrupt(digitalPinToInterrupt(D7), buttonpress, FALLING);
 strip.begin();
 strip.show();
}
void loop() 
{
}
void buttonpress()
{
 // button 1 ==> 011
 if (digitalRead(D5)== LOW && digitalRead(D6)== HIGH && digitalRead(D7)== HIGH)
 {
 strip.setPixelColor(0, 0,255,0); 
 strip.setPixelColor(1, 0,0,0);
 strip.setPixelColor(2, 0,0,0);
 strip.setPixelColor(3, 0,0,0);
 strip.setPixelColor(4, 0,0,0);
 strip.setPixelColor(5, 0,0,0);
 strip.setPixelColor(6, 0,0,0);
 strip.show(); 
 delay(500);
 }
 // button 2 ==> 101
 if (digitalRead(D5)== HIGH && digitalRead(D6)== LOW && digitalRead(D7)== HIGH)
 {
 strip.setPixelColor(0, 0,255,0); 
 strip.setPixelColor(1, 0,255,0);
 strip.setPixelColor(2, 0,0,0);
 strip.setPixelColor(3, 0,0,0);
 strip.setPixelColor(4, 0,0,0);
 strip.setPixelColor(5, 0,0,0);
 strip.setPixelColor(6, 0,0,0);
 strip.show(); 
 delay(500);
 }
 // button 3 ==> 110
 if (digitalRead(D5)== HIGH && digitalRead(D6)== HIGH && digitalRead(D7)== LOW)
 {
 strip.setPixelColor(0, 0,255,0); 
 strip.setPixelColor(1, 0,255,0);
 strip.setPixelColor(2, 0,255,0);
 strip.setPixelColor(3, 0,0,0);
 strip.setPixelColor(4, 0,0,0);
 strip.setPixelColor(5, 0,0,0);
 strip.setPixelColor(6, 0,0,0); 
 strip.show(); 
 delay(500);
 }
 // button 4 ==> 100
 if (digitalRead(D5)== HIGH && digitalRead(D6)== LOW && digitalRead(D7)== LOW) //
 {
 strip.setPixelColor(0, 0,255,0); 
 strip.setPixelColor(1, 0,255,0);
 strip.setPixelColor(2, 0,255,0);
 strip.setPixelColor(3, 0,255,0);
 strip.setPixelColor(4, 0,0,0);
 strip.setPixelColor(5, 0,0,0);
 strip.setPixelColor(6, 0,0,0);
 strip.show(); 
 delay(500);
 }
 // button 5 ==> 001
 if (digitalRead(D5)== LOW && digitalRead(D6)== LOW && digitalRead(D7)== HIGH) //
 {
 strip.setPixelColor(0, 0,255,0); 
 strip.setPixelColor(1, 0,255,0);
 strip.setPixelColor(2, 0,255,0);
 strip.setPixelColor(3, 0,255,0);
 strip.setPixelColor(4, 0,255,0);
 strip.setPixelColor(5, 0,0,0);
 strip.setPixelColor(6, 0,0,0);
 strip.show(); 
 delay(500);
 }
 // button 6 ==> 010
 if (digitalRead(D5)== LOW && digitalRead(D6)== HIGH && digitalRead(D7)== LOW) //
 {
 strip.setPixelColor(0, 0,255,0); 
 strip.setPixelColor(1, 0,255,0);
 strip.setPixelColor(2, 0,255,0);
 strip.setPixelColor(3, 0,255,0);
 strip.setPixelColor(4, 0,255,0);
 strip.setPixelColor(5, 0,255,0);
 strip.setPixelColor(6, 0,0,0);
 strip.show(); 
 delay(500);
 }
 // button 7 ==> 000
 if (digitalRead(D5)== LOW && digitalRead(D6)== LOW && digitalRead(D7)== LOW) //
 {
 strip.setPixelColor(0, 0,255,0); 
 strip.setPixelColor(1, 0,255,0);
 strip.setPixelColor(2, 0,255,0);
 strip.setPixelColor(3, 0,255,0);
 strip.setPixelColor(4, 0,255,0);
 strip.setPixelColor(5, 0,255,0);
 strip.setPixelColor(6, 0,255,0); 
 strip.show(); 
 delay(500);
 }
}


Before I get a load of comments in my mail on this code let me make it clear that this source code can be optimised a lot. That would make it a lot more complicated for beginning programmers to comprehend. So adjust it for your own purposes.

The program starts with initialising the Neopixel library and attaching the library to pin D8.

In the setup routine the input lines D5, D6 and D7 are defined, and we attach an interrupt to each of these lines. All the interrupts point to the same routine: buttonpress on a FALLING signal. This means that when a button is pressed (connected to ground) the program starts the interrupt routine.

This is a big advantage over the software for the commercial keyboards. Your software is not constant sending LOW signals to row-pins and polling the collumn-pins. We just wait till a key is pressed and in the mean time the micro-controller has loads of time for other tasks.

When a button is pressed the program jumps to the buttonpress() routine.

Here is a closer examination about what happens when button 4 is pressed:

// button 4 ==> 100
if (digitalRead(D5)== HIGH && digitalRead(D6)== LOW && digitalRead(D7)== LOW) //
{
strip.setPixelColor(0, 0,255,0);
strip.setPixelColor(1, 0,255,0);
strip.setPixelColor(2, 0,255,0);
strip.setPixelColor(3, 0,255,0);
strip.setPixelColor(4, 0,0,0);
strip.setPixelColor(5, 0,0,0);
strip.setPixelColor(6, 0,0,0);
strip.show();
delay(500);
}

The diodes from button 4 are attached to D6 and D7. So when button 4 is pressed D5 will get no signal and the pull-up resistor makes sure the line is HIGH. Line D6 and D7 will be connected to ground. This is what the if statement analyses.

Next part is just setting 4 of the neopixels to green, so we know for sure button 4 is pressed. The delay makes sure that the neopixels are lit before we go on.

Simple and efficient !!!
We got lots of room and time for the processor to perform other tasks in stead of constant sending signals and polling lines and have the risk of missing a keypress.

You will notice that the only thing you have to do is to alter D5, D6, D7 and D8 and this will also work on the ESP32 or any of the Arduino family even on the humble Attiny85 !!!

Basic program

No I am not forgetting ESP-Basic, - my used to be - favorite rapid devellopment environment (that's a mouth full). In fact the hardware setup is so efficient that writing the software in Basic is very easy. It looks a lot like the C++ program.



interrupt d5, [CHANGE]
interrupt d6, [CHANGE]
interrupt d7, [CHANGE]
neo.setup(d8)
neo.cls()
wait
[CHANGE] 
interrupt d5
interrupt d7
interrupt d6
if ((io(pi,d5) = 0) and (io(pi,d6) = 1) and (io(pi,d7) = 1)) then
neo.cls()
neo(0,250,250,250)
endif
 
if ((io(pi,d5) = 1) and (io(pi,d6) = 0) and (io(pi,d7) = 1)) then
neo.cls()
neo(0,250,250,250)
neo(1,250,250,250)
endif
if ((io(pi,d5) = 1) and (io(pi,d6) = 1) and (io(pi,d7) = 0)) then
neo.cls()
neo(0,250,250,250)
neo(1,250,250,250)
neo(2,250,250,250)
endif
if ((io(pi,d5) = 1) and (io(pi,d6) = 0) and (io(pi,d7) = 0)) then
neo.cls()
neo(0,0,0,250)
neo(1,0,0,250)
neo(2,0,0,250)
neo(3,0,0,250)
endif
if ((io(pi,d5) = 0) and (io(pi,d6) = 0) and (io(pi,d7) = 1)) then
neo.cls()
neo(0,250,0,0)
neo(1,250,0,0)
neo(2,250,0,0)
neo(3,250,0,0)
neo(4,250,0,0)
endif
if ((io(pi,d5) = 0) and (io(pi,d6) = 1) and (io(pi,d7) = 0)) then
neo.cls()
neo(0,0,250,0)
neo(1,0,250,0)
neo(2,0,250,0)
neo(3,0,250,0)
neo(4,0,250,0)
neo(5,0,250,0)
endif
if ((io(pi,d5) = 0) and (io(pi,d6) = 0) and (io(pi,d7) = 0)) then
neo.cls()
neo(0,250,0,250)
neo(1,250,0,250)
neo(2,250,0,250)
neo(3,250,0,250)
neo(4,250,0,250)
neo(5,250,0,250)
neo(6,250,0,250)
endif
delay (500)
interrupt d6, [CHANGE]
interrupt d7, [CHANGE]
interrupt d5, [CHANGE]
delay (500)
cls
wait 
end


A quick examination of the program:

interrupt d5, [CHANGE]
interrupt d6, [CHANGE]
interrupt d7, [CHANGE]

neo.setup(d8)
neo.cls()

wait

This is the main part where the interrupts are defined and the neopixels are attached to IO pin D8

[CHANGE]

interrupt d5
interrupt d7
interrupt d6

This is a tricky part.

If the [CHANGE] routine is called (as a button is pressed) we do not want that the routine is accidentally (think bouncing buttons) called again. So these commands disable the interrupts.

if ((io(pi,d5) = 1) and (io(pi,d6) = 0) and (io(pi,d7) = 0)) then
neo.cls()
neo(0,0,0,250)
neo(1,0,0,250)
neo(2,0,0,250)
neo(3,0,0,250)
endif

This is almost the same as in the C++ routine and is the part where button 4 is processed.
As you can see D5 gets no signal so that will be pulled HIGH by the pull-up resistors. D6 and D7 should both get a LOW signal. If this is true the first 4 neopixels (0 to 3) will be set to blue.

interrupt d6, [CHANGE]
interrupt d7, [CHANGE]
interrupt d5, [CHANGE]

These lines will activate the interrupts anew when the routine has finished.

As there are two delay (500) statements the program will register a button-press once every second. That should be fast enough for most purposes.

Expanding

Using 4 I/O pins you can attach 15 buttons which is enough for a simple calculator keyboard. And with 5 I/O pins you can attach 31 buttons !!
I am sure you can work the schematics out for yourselves.

Let's elaborate on this.
With 5 I/O pins you can attach 31 buttons. Now suppose you use one of these 31 buttons as a Shift key and another one as a Second Function key you could build a simple ASCII keyboard using an Arduino Pro Micro which has a real USB interface.

Pros and cons.

So why isn't this used more often, and why are all the commercial keyboards build as a matrix ssytem and not in this way.
The answer is simple: costs.
Using the matrix layout you only need buttons. In this setup you need buttons and diodes which is more expensive and makes the PCB a bit more complicated.

The pros for me weigh much more as the cons.
For the 12 button commercial version you will need to use 7 I/O pins on your controller. I only need 4 and can use 15 buttons (3 more).
The additional costs are so small that they are neglectable. At the moment of this writing you can buy 100 diodes for 50 cents !!!
Next to that the software does not put a heavy load on my controller and is much easier to program.

And last but not least: on an Attiny85 I can attach 15 buttons and a string of neopixels at the same time !!!

Real world setup




Above you can see my real world setup and test. The only difference with the schematics in this story is that I attached a seperate power supply for the Neopixels.

That's it for now.

Till next time and have fun.

Luc Volders

Friday, March 11, 2022

ESP webserver tutorial part 5 - Neopixel control

For a complete index to all my articles click this text.

This is a series on building a webpage with the ESP8266 and the ESP32. When this series is completed all the information on building a webpage with buttons, textfields, sliders and color pickers witch have interaction with the ESP8266 or ESP32 will be discussed and demonstrated.

This fifth part leans heavy on the previous four parts in this series, so I urge you to read these stories first:

ESP webserver tutorial part 1 - textfields
ESP webserver tutorial part 2 - button
ESP webserver tutorial part 3 - button with save
ESP webserver tutorial part 4 - slider

The last part showed you how to build a webpage with the ESP8266 and ESP32 that incorporates a slider with which you can dim a led.



As promised in that story I am going to show you here how to build a webpage with 3 sliders with which you can control the colors of a ledstrip. The ledstrip I am going to use here is a strip of Neopixels.


Again I am writing the program in Arduino language (C++)

As a bonus there is a nice trick build into the software that makes the colors change automatically when you alter the slider settings. You do not have to press a confirmation button as was required in the previous story.

The ESP8266 breadboard setup.

The breadboard setup is off course different from the setup in the previous stories because we are goiung to attach a neopixels strip to the ESP8266. You can find a full blown explanation/tutorial on Neopixels in a previous story on my weblog which you can find here:
http://lucstechblog.blogspot.com/2015/10/neopixels-ws2812-intro.html



In this setup I used an ESP8266 (the3 Wemos D1 mini version). The Neopixelstrip is connected to D7 with a current delimiting resistor of 470 Ohm. And a large capacitor for stabilising the current is connected over the power lines (mind the polarity). I used the symbol of an existing neopixel strip from the fritzing library but you may use a ring of strip or even matrix of your own liking. Keep the amount of neopixels low (like 7 to 8) and you can get the current directly from the ESP8266. If you want to attach a larger amount of neopixels make sure you give them an external power supply.

The ESP32 breadboard setup.

The ESP32 breadboard setup is equally simple.



I am using the ESP32 Devkit board. These boards will not fit a breadboard. Therefore I use 2 breadboards. From one of these breadboards I stripped the power rail as discussed in the story you can read here:
https://lucstechblog.blogspot.com/2018/08/breadboard-hack-for-esp32-and-esp8266.html

The led is attached to GPIO22 through a 470 Ohm current delimiting resistor, and there is a large capacitor connected to the power rail to stabilising the current.
I attached an external USB power connector because the ESP32 consumes a lot of power in itself and attaching a ledstrip might impose too much to its power leads.
You can find a detailed explanation on powering the ESP32 in my book (which is in Dutch or English) called ESP32 uitgelegd and in English ESP32 Simplified on which you can find detailed info here:
http://lucstechblog.blogspot.com/2019/07/esp32-uitgelegd-nu-verkrijgbaar.html

and here https://lucstechblog.blogspot.com/2020/10/esp32-simplified-world-wide-available.html

You can find a story on external powering the ESP microcontrollers here:
https://lucstechblog.blogspot.com/2017/10/powering-your-project.html

The program

Just like the previous entries in this series the program is written in Arduino language (C++) and is almost identical for the ESP8266 and the ESP32. The changes for the ESP32 are really minimal. I will give you the ESP8266 program as a whole and you can find the few lines which have to be modified for the ESP32 at the end of this story.


// ======================================================
// Libraries needed
// ======================================================
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Adafruit_NeoPixel.h>
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 7
// Your credentials
ESP8266WebServer server(80);
const char* ssid = "XXXXXXXXXXXXXXX";
const char* password = "YYYYYYYYYYYYYY";
int neoPin = D7; 
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, neoPin, NEO_GRB + NEO_KHZ800);
String responseHTML = ""
 "<!DOCTYPE html><html><head><title>CaptivePortal</title></head><body>"
 "<h1>Hello World!</h1><p>This is a captive portal example. All requests will "
 "be redirected here.</p></body></html>";
// ==========================================
// initial variables
// ========================================== 
int sliderREDvalue = 0;
int sliderGREENvalue = 0;
int sliderBLUEvalue = 0;
// =========================================
// Build the webpage
// =========================================
String getPage()
 {
 String page = "<!DOCTYPE HTML>";
 page += "<html>";
 page += "<head>";
 page += "<meta name = \"viewport\" content = \"width = device-width, initial-scale = 1.0 maximum-scale = 2.5, user-scalable=1\">";
 page += "<title>Luc's Neopixels slider demo</title>";
 page += "<style>";
 page += "body { background-color: powderblue}";
 page += "</style>";
 page += "</head>";
 page += "<body>";
 page += "<h1 style='color:red'>Luc's Neopixels slider demo</h1>";
 page += "<form id=\"myForm\" action=\"/\" method=\"post\">";
 page += "Move the slider for choosing the color :<br><br>";
 page += "RED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
 page += "<input type=\"range\" min=\"0\" max=\"255\" onmouseleave=\"myFunction()\" id=\"sliderred\" name=\"sliderred\" value=\"";
 page += sliderREDvalue;
 page +="\" > <br>";
 
 page += "GREEN&nbsp;&nbsp;&nbsp;";
 page += "<input type=\"range\" min=\"0\" max=\"255\" onmouseleave=\"myFunction()\" id=\"slidergreen\" name=\"slidergreen\" value=\"";
 page += sliderGREENvalue;
 page +="\" > <br>";
 
 page += "BLUE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
 page += "<input type=\"range\" min=\"0\" max=\"255\" onmouseleave=\"myFunction()\" id=\"sliderblue\" name=\"sliderblue\" value=\"";
 page += sliderBLUEvalue;
 page +="\" > <br>";
 page += "</form>";
 page += "<br>";
 page += "<script>";
 page += "function myFunction() {";
 page += "document.getElementById(\"myForm\").submit()";
 page +="}";
 page +="</script>";
 page += "</body>";
 page += "</html>";
 return page;
 }
// ==========================================
// Handle if unknown command
// ==========================================
void handleNotFound()
{
 server.send(200, "text/html", getPage());
}
// ===========================================
// Submit page
// ===========================================
void handleSubmit()
 {
 if (server.hasArg("slidergreen"))
 {
 sliderGREENvalue = server.arg("slidergreen").toInt();
 Serial.print("The slider Green has value: ");
 Serial.println(sliderGREENvalue);
 for(int i=0;i<NUMPIXELS;i++)
 {
 // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
 pixels.setPixelColor(i, pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue)); // Moderately bright green color.
 pixels.show(); // This sends the updated pixel color to the hardware.
 }
 }
 if (server.hasArg("sliderred"))
 {
 sliderREDvalue = server.arg("sliderred").toInt();
 Serial.print("The slider Red has value: ");
 Serial.println(sliderREDvalue);
 for(int i=0;i<NUMPIXELS;i++)
 {
 // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
 pixels.setPixelColor(i, pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue)); // Moderately bright green color.
 pixels.show(); // This sends the updated pixel color to the hardware.
 }
 } 
 if (server.hasArg("sliderblue"))
 {
 sliderBLUEvalue = server.arg("sliderblue").toInt();
 Serial.print("The slider Blue has value: ");
 Serial.println(sliderBLUEvalue);
 for(int i=0;i<NUMPIXELS;i++)
 {
 // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
 pixels.setPixelColor(i, pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue)); // Moderately bright green color.
 pixels.show(); // This sends the updated pixel color to the hardware.
 }
 } 
 server.send(200, "text/html", getPage()); //Response to the HTTP request
 } 
// =============================================
// Test if commands received
// =============================================
void handleRoot() 
 { 
 if (server.args() ) 
 {
 handleSubmit();
 } 
 else 
 {
 server.send(200, "text/html", getPage()); 
 }
 }
// =============================================
// Setup
// =============================================
void setup()
 {
 delay(1000);
 Serial.begin(115200);
 // WiFi initilisation part
 // Connect to Wi-Fi network with SSID and password
 Serial.print("Connecting to ");
 Serial.println(ssid);
 WiFi.begin(ssid,password);
 while (WiFi.status() != WL_CONNECTED) 
 {
 delay(500);
 Serial.print(".");
 }
 // Print local IP address and start web server
 Serial.println("");
 Serial.println("WiFi connected.");
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());
 server.begin();
 server.on("/", handleRoot);
 server.onNotFound(handleNotFound);
 delay(500);
 pixels.begin(); // This initializes the NeoPixel library.
 
 pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue);
 pixels.show();
 }
// ===============================================
// LOOP
// =============================================== 
void loop()
 { 
 server.handleClient(); 
 delay(50);
 }

The program is almost identical to the program in the previous stories. All explanation therefore has been done in those stories except for the few lines that are required for putting the three sliders on the screen. This is done in the <form> part of the webpage.

First we need to activate the neopixels code and that is done by these entries at the beginning of the program:


#include <Adafruit_NeoPixel.h>
int neoPin = D7;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, neoPin, NEO_GRB + NEO_KHZ800);

As you can see the neopixels code is attached to I/O pin D7.

int sliderREDvalue = 0;
int sliderGREENvalue = 0;
int sliderBLUEvalue = 0;

The above lines make sure that the neopixels are set off when the program starts.

In the setup() routine at the end of the program the IP adress is printed in the Serialmonitor so you will know which IP adress you should fill in on your computers or phones browser to find the webpage.

 pixels.begin(); // This initializes the NeoPixel library.
 pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue);
 pixels.show();

These lines activate the neopixels and set the color to the initial values which were defined at the start of the program (0,0,0).

The important changes are in the HTML code where the form is made and the sliders defined.

 page += "<form id=\"myForm\" action=\"/\" method=\"post\">";
 page += "Move the slider for choosing the color :<br><br>";
 page += "RED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
 page += "<input type=\"range\" min=\"0\" max=\"255\" onmouseleave=\"myFunction()\" id=\"sliderred\" name=\"sliderred\" value=\"";
 page += sliderREDvalue;
 page +="\" > <br>";
 page += "GREEN&nbsp;&nbsp;&nbsp;";
 page += "<input type=\"range\" min=\"0\" max=\"255\" onmouseleave=\"myFunction()\" id=\"slidergreen\" name=\"slidergreen\" value=\"";
 page += sliderGREENvalue;
 page +="\" > <br>";
 page += "BLUE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
 page += "<input type=\"range\" min=\"0\" max=\"255\" onmouseleave=\"myFunction()\" id=\"sliderblue\" name=\"sliderblue\" value=\"";
 page += sliderBLUEvalue;
 page +="\" > <br>";
 page += "</form>";

As you can see there are some things different from the program in the previous story.

page += "RED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";

After each name of the slider I put some &nbsp commands wich will neatly lineup the sliders. You could do this even better by putting the names of the sliders and the sliders itself into a table. A nice HTML excercise for those who want to expand their knowledge.

Now lets look at the html code that defines the red slider.

page += "<input type=\"range\" min=\"0\" max=\"255\" onmouseleave=\"myFunction()\" id=\"sliderred\" name=\"sliderred\" value=\"";

The first part is easy to understand. The type of input is range which means a slider and the minimum and maximum values are defined.
onmouseleave is an HTML function that is activated when the mouse moves over the slider and then leaves its aerea. When that happens the function myFunction() is called.

The code for the green and blue sliders is almost identical as you can see. The difference is in the id and name settings.

page += "<script>";
page += "function myFunction() {";
 page += "document.getElementById(\"myForm\").submit()";
page +="}";
page +="</script>";

At the end of the HTML page the Javascript function myFunction is called when the mouse has left the area of one of the sliders. This code actually takes the values of the sliders from the form and uses submit() to send them to the webserver.

In the handlesubmit() routine the webserver receives the information from the form on the webpage and the slider settings are analysed. Every slider info is analysed individually and processed. Lets look at the information from the green slider coming in:

 if (server.hasArg("slidergreen"))
 {
 sliderGREENvalue = server.arg("slidergreen").toInt();
 Serial.print("The slider Green has value: ");
 Serial.println(sliderGREENvalue);
 for(int i=0;i<NUMPIXELS;i++)
 {
 // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
 pixels.setPixelColor(i, pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue)); // Moderately bright green color.
 pixels.show(); // This sends the updated pixel color to the hardware.
 }
 }

As you can see the name slidergreen is the name that is tested for. That is why each slider got his own name and ID in the above mentioned HTML code.
The received value is put into the sliderGREENvalue variable and printed in the Serialmonitor.
Then the information is send to the neopixels strip. All slider values are send so the settings of the other colors is not changed unless their sliders have been changed.

Dont forget the pixels.show() command. that will actually activate the new settings.

ESP32 code

Well there is not much difference in the ESP8266 and ESP32 code on the software side.

The same Adafruit Neopixel library is used as for the ESP8266 as its compatible for both. We only have to alter the pin assignment as you can see in the breadboard setup. The Neopixels are attached to pin 22.

int neoPin = D7;

And for the webserver we only have to Change the following lines:

#include <ESP8266WiFi.h>;
#include <ESP8266WebServer.h>;
ESP8266WebServer server(80);

into:

#include <WiFi.h>;
#include <WebServer.h>;
WebServer server(80);

Thats all.

Pitfall.

The above code works flawlessly on my PC with Windows 10 in the Firefox and Chrome browsers. There is however a problem with this code which is not really interesting when you use it to control a ledstrip or neopixels. It might impose a problem if you are going to use this for steering a motor, pump or likewise.


As you can see the slidervalues are send very often to the webserver and processed. Indeed evrytime you move your mouse over a slider even if you did not alter it. So if you alter and use this code to send PWM values to a motor or pump the motor might hick up everytime the info is send and processed in the webserver.

You can avoid this by changing onmouseleave in onblur like this in the red slider code:


page += "<input type=\"range\" min=\"0\" max=\"255\" onblur=\"myFunction()\" id=\"sliderred\" name=\"sliderred\" value=\"";

Pitfall 2

Another pitfall is that this code does not work on Android phones (and Iphones for that) because the html onmouse functions are not compatble with touch screens.

So to get this working on PC and on Android systems we sadly have to revert to the old system where a button is pressed after the slider has been changed. I will give you the code for this here in its total without any explanation and am sure you can figure it out yourself.


// ======================================================
// Libraries needed
// ======================================================
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Adafruit_NeoPixel.h>
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 7
// Your credentials
ESP8266WebServer server(80);
const char* ssid = "ZyXEL9680AC";
const char* password = "B9BB53BCA049";
int neoPin = D7; 
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, neoPin, NEO_GRB + NEO_KHZ800);
String responseHTML = ""
 "<!DOCTYPE html><html><head><title>CaptivePortal</title></head><body>"
 "<h1>Hello World!</h1><p>This is a captive portal example. All requests will "
 "be redirected here.</p></body></html>";
// ==========================================
// initial variables
// ========================================== 
int sliderREDvalue = 0;
int sliderGREENvalue = 0;
int sliderBLUEvalue = 0;
// =========================================
// Build the webpage
// =========================================
String getPage()
 {
 String page = "<!DOCTYPE HTML>";
 page += "<html>";
 page += "<head>";
 page += "<meta name = \"viewport\" content = \"width = device-width, initial-scale = 1.0 maximum-scale = 2.5, user-scalable=1\">";
 page += "<title>Luc's Neopixels slider demo</title>";
 page += "<style>";
 page += "body { background-color: powderblue}";
 page += "</style>";
 page += "</head>";
 page += "<body>";
 page += "<h1 style='color:red'>Luc's Neopixels slider demo</h1>";
 page += "<form action=\"/\" method=\"post\">";
 page += "Move the slider for choosing the color :<br><br>";
 page += "RED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
 page += "<input type=\"range\" min=\"0\" max=\"255\" id=\"sliderred\" name=\"sliderred\" value=\"";
 page += sliderREDvalue;
 page +="\" class=\"slider\"> <br>";
 
 page += "GREEN&nbsp;&nbsp;&nbsp;";
 page += "<input type=\"range\" min=\"0\" max=\"255\" id=\"slidergreen\" name=\"slidergreen\" value=\"";
 page += sliderGREENvalue;
 page +="\" class=\"slider\"> <br>";
 
 page += "BLUE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
 page += "<input type=\"range\" min=\"0\" max=\"255\" id=\"sliderblue\" name=\"sliderblue\" value=\"";
 page += sliderBLUEvalue;
 page +="\" class=\"slider\"> <br><br>";
 page += "<input type=\"submit\" value=\"Confirm\">";
 page += "</form>";
 page += "<br>";
 page += "<br>";
 page += "<br>";
 page += "</body>";
 page += "</html>";
 return page;
 }
// ==========================================
// Handle if unknown command
// ==========================================
void handleNotFound()
 {
 server.send(200, "text/html", getPage());
 }
// ===========================================
// Submit page
// ===========================================
void handleSubmit()
 {
 if (server.hasArg("slidergreen"))
 {
 sliderGREENvalue = server.arg("slidergreen").toInt();
 Serial.print("The slider has value: ");
 Serial.println(sliderGREENvalue);
 for(int i=0;i<NUMPIXELS;i++)
 {
 // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
 pixels.setPixelColor(i, pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue)); // Moderately bright green color.
 pixels.show(); // This sends the updated pixel color to the hardware.
 }
 }
 if (server.hasArg("sliderred"))
 {
 sliderREDvalue = server.arg("sliderred").toInt();
 Serial.print("The slider has value: ");
 Serial.println(sliderREDvalue);
 for(int i=0;i<NUMPIXELS;i++)
 {
 // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
 pixels.setPixelColor(i, pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue)); // Moderately bright green color.
 pixels.show(); // This sends the updated pixel color to the hardware.
 }
 } 
 if (server.hasArg("sliderblue"))
 {
 sliderBLUEvalue = server.arg("sliderblue").toInt();
 Serial.print("The slider has value: ");
 Serial.println(sliderBLUEvalue);
 for(int i=0;i<NUMPIXELS;i++)
 {
 // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
 pixels.setPixelColor(i, pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue)); // Moderately bright green color.
 pixels.show(); // This sends the updated pixel color to the hardware.
 }
 } 
 server.send(200, "text/html", getPage()); //Response to the HTTP request
} 
// =============================================
// Test if commands received
// =============================================
void handleRoot() 
 { 
 if (server.args() ) 
 {
 handleSubmit();
 } 
 else 
 {
 server.send(200, "text/html", getPage()); 
 }
 }
// =============================================
// Setup
// =============================================
void setup()
 {
 delay(1000);
 Serial.begin(115200);
 // WiFi initilisation part
 // Connect to Wi-Fi network with SSID and password
 Serial.print("Connecting to ");
 Serial.println(ssid);
 WiFi.begin(ssid,password);
 while (WiFi.status() != WL_CONNECTED) 
 {
 delay(500);
 Serial.print(".");
 }
 // Print local IP address and start web server
 Serial.println("");
 Serial.println("WiFi connected.");
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());
 server.begin();
 server.on("/", handleRoot);
 server.onNotFound(handleNotFound);
 server.begin();
 delay(500);
 pixels.begin(); // This initializes the NeoPixel library.
 
 pixels.Color(sliderREDvalue,sliderGREENvalue,sliderBLUEvalue);
 pixels.show();
 }
//++++++++++++++++++++++++++++++++++++++++++++++//
// LOOP //
//++++++++++++++++++++++++++++++++++++++++++++++//
void loop()
 { 
 server.handleClient(); 
 delay(50);
 }


This will look on your PC screen like this.



On android it looks like this.



Going further.

So there you have it a complete means to put sliders on a webpage and control the ESP8266 or ESP32 with them.

There are several uses for this. You can change the hardware and code to use this with RGB ledstrips in stead of Neopixels. The webserver software should not be difficult to adapt. You can find the hardware here:
https://lucstechblog.blogspot.com/2018/04/rgb-strip-control-over-wifi-part-2.html

You could also use this to rebuild the remote controlled car which I showed you in a previous story and in which the software was written in ESPBasic which you can find here: http://lucstechblog.blogspot.com/2019/02/remote-controlled-car-with-wifi.html

And combining buttons and a slider you could even rewrite the tea-timer I build in this story: https://lucstechblog.blogspot.com/2018/08/teatimer.html

And like stated earlier in this story you could make the webpage more structured by putting the texts and sliders in a table. You can learn how to do that and everything else about HTML and javascript from this website: https://www.w3schools.com/

Now you have all the tools to make a decent webpage and control your ESP8266 or ESP32 from this page and even put all kind of sensor values on this page.


In the past I always have used ESPBasic as my favorite devellopment environment. Unfortunately ESPBasic is not further develloped and there is no ESP32 version available. This method of building a webserver makes it easy to replace ESPBasic with the standard Arduino environment for both ESP versions. So it is slowly time to say goodbye to ESPBasic.

Go ahead and build a project using this. I will give you a complete project in an upcoming story. So stay tuned.

Have fun.

Luc Volders

Subscribe to: Comments (Atom)

AltStyle によって変換されたページ (->オリジナル) /