Friday, February 15, 2019

Simple IFTTT webhook test

 For an index to all my stories click this text

Time flies !!! I just can not believe it is already 2 year ago when I wrote my first weblog entry about IFTTT

For those who are still unaware about what IFTTT is read my 2 introduction stories here:
https://lucstechblog.blogspot.com/2017/04/ifttt-if-this-then-that.html
https://lucstechblog.blogspot.com/2017/05/ifttt-part-2-maker-channel.html

And read about a movement detection system using IFTTT to get an alarm on your phone here:
https://lucstechblog.blogspot.com/2017/05/ifttt-part-3-basic-alert-over-ifttt.html

Last november I brought you another story on how to use IFTTT in a practical way. I used a sensor to trigger an alarm when an object (in my case a painting) was moved:
https://lucstechblog.blogspot.com/2018/11/alarm.html

IFTTT Quick test

During devellopping a new project with IFTTT I needed a quick way to test wether my IFTTT setup worked.
Sending a trigger from an ESP8266 looks like a good idea. But what if it does not work. Is the problem in the ESP-code or is the IFTTT applet not setup in the right way.

So I discovered a neat trick to test the IFTTT applet.

First setup the IFTTT applet like you have seen in the alarm story:
https://lucstechblog.blogspot.com/2018/11/alarm.html


 

The event name we used in IFTTT is alarm.






Now just open your browser and type in:

https://maker.ifttt.com/trigger/alarm/with/key/PUTYOUROWNKEYHERE

press Enter and a notification will be triggered on your phone. This will work in any browser . Meaning it will work in the browser on your computer, phone and tablet.






This is a nice quick way to test IFTTT webhook applets.

Android 9 pitfall:

Android 9 has at the moment of this writing a serious battery problem. To prevent draining the battery of your phone best practice is to put all notifications off. However when notifications for IFTTT are set off you will not get the alarm on your phone. So make sure notifications for IFTTT are turned on.

Till next time

Luc Volders

Friday, February 8, 2019

Remote controlled car with Wifi

For an idex to all my stories click this text 


As a kid I was fascinated by remote controlled cars. I never owned one but several of my friends had one. I did not envy them because just driving around such a car and running after it was not really my idea of fun. It just intrigued me how such a thing worked.

A few years ago when I was building my own 3D printer, just before I really dug into electronics, I started to comprehend how the electronics to control motors and stepper motors work. And now surfing all kinds of technical websites I got interested in remote controlled cars again. How difficult could it be ?? A transmitter, a receiver, a transistor to send a strong current to the motor and you're done. Piece of cake or not ??

Forward is easy

Controlling a motor is one of the fundamental excersises when you start learning Arduino and electronics. An arduino can not provide enough current to control a motor. So you will have to reinforce the signal from the arduino with a transistor. I have done this before on this weblog when I was controlling a ledstrip. The drill is basically the same. So let's look at the most simple setup.



Here you can see that a signal from your micro controller (wether it is an Arduino, ESP or Raspberry) is send through an 100 Ohm resistor into a transistor which then send a large current to a ledstrip. So the only thing we have to do is to exchange the ledstrip for a motor and we're off.

The software only has to put one of the digital outputs to high to get the motor running. Set it to low and the motor stops. So we can go forward and we can stop. How about turns ??

Turning left and right.

Well this is easy to. For strength we will use two motors to drive the car. Turning to the left is easily done by stopping the left motor and running the right one. Turning to the right is just the opposite. Stop the right motor and run the left one.

H-Bridge

So with these simple steps we can go forward, left and right. But we also need to drive backwards. That is more complicated. To get the motor running in the opposite direction you need to switch polarity, and that is easier said as done.

Long time ago a solution was found for this problem and it is called an H-Bridge. Basically at first this was achieved with switches. Just look at the next schematics.


First look at the left side.

The switch on the top left side is open and the switch on the bottom right side is open. So the cirrent can only pass on the top right side through the motor and then down. The motor therefore runs in one direction.

Now look at the right side.

The switch on the top left side is closed and the one on the bottom right side is closed. Just the opposite of the previous state. In this situation the currect has to flow from the right side through the motor to the left side. And that makes the motor run in the other direction.

This works great. However done with switches it can not be operated remotely. Well actually it can !! and it was done in the early days. I still remember remote controlled cars with a wired remote...... But that is not what we are trying to achieve.

Fortunately electronics come to the rescue.



An electronic H-Bridge can be made by pairs of NPN and PNP transistors.
The electronic H-Bridge works the same way as the mechanical one. The switching is done by a small current send to the base of the transistors. This works because the NPN transistors allow current to flow when the base voltage is high, and the PNP transistors allow current to flow when the base voltage is low.

As you can see this can easily be build by yourself. For two motors you will need two of these circuits.

Let's make things easier.

As running motors is very popular dedicated H-Bridge IC's are widely available.
We are going to use the popular L293D.

 
As you can see it is easy to use. The IC is build up symetrically, and can control 2 motors at the same time. On the left side there is a VCC connection and in the middle 2 GND pins. Next to the GND are the motor connections and next to that the input pins which can be attached directly to an Arduino, ESP8266 or a Raspberry Pi.
The right side has the same connections mirrorred. So with this you can attach two motors and control them by 4 pins from your microcontroller.

Set one IO port of the controller HIGH and the other LOW and the motor will run forward. Switch the HIGH and LOW and the motor will run backwards.

 


For completeness I herebye give you the pin layout.

The L293D has some impressive features. It will run motors up to 600Ma and it can drive motors, solenoids and even steppers.

Make sure you opt for the L293D version. This one has clamping diodes that makes extra electronics unnecessary. You can also choose the SN754410 which has the same pinout so can be exchanged 1 on1 in the setup. However the SN754410 can supply a larger current (1A) so can be used for stronger motors.

Speed

Going forward and backward is one thing. But by setting the IO pins to 1 or 0 will just make the motor run at full speed or stop.

What we want is speed control. And that is where PWM comes in.

Luckily all modern micro controllers like the Ardiuino, ESP and even the Raspberry have PWM control. I presume you have used it yourself in your projects to dim a led for example.

For those not familiar with the term. PWM is the digital equivalent of setting the voltage on an IO pin. Normally the pin would be LOW or HIGH. And HIGH will be 5Volt or 3.3Volt depending on your micro controller. By setting the PWM value of an IO pin you can set the output voltage of that pin on any value between LOW and HIGH.

Actually it is a bit more complicated. The PWM function sets the pin alternately HIGH and LOW but in a very fast pace and that makes it look like a certain voltage. That is the theory. In real life for most electronics it looks like a variable voltage and that can regulate the speed of our motors.

Wireless remote control.

Several options come to my mind.
- Attach a bluetooth controller and an LD293D to an arduino and write an app with app-inventor to control it
- Attach 433Mhz transmitter to an arduino and use potmeters to set speed and direction. Use a second arduino with a 433Mhz receiver to control the LD293D. This will give you a larger range.
- Attach a NRF24L01 instead of the 433Mhz version described in the preivious point.
- Attach the LD293D to an ESP8266 and control it from a webpage.

Well to get things up and running fast I choose the easy way out (again). I choose my preferred rapid devellopment tool: ESPBasic. If you have never worked with ESPBasic before I urge you to read my introduction story which you can find here:
https://lucstechblog.blogspot.nl/2017/03/back-to-basic-basic-language-on-esp8266.html

Before we look at the program let us have a look at the hardware setup.




As you can see I attached the L293D motor 1 pins to pin D0 and D1 of the ESP and motor 2 pins to D2 and D4.
For testing purposes (before I mounted everything on a frame) I attached leds to the control pins so I had a visual indication to the direction of the motors. In the finished model I left the leds out. You can leave them in and use them as headlights.



So far for all the theory now is the time to try it out real time. Therefore I used a powerfull powerbank that has 2 USB outputs. The first one supplies max 1 amp and that is attached to the ESP. The second USB output supplies 2 amps and that is connected to the power rail of the breadboard to power the LD293D that directly powers the motors.



The motors and wheels I used are the standard versions that can be bought for a few dollar from your favorite Chinese supplier.


From the local dollar store I bought some cheap caster wheels. The motors are used for the front weels and on the back there is just one caster wheel.


When everything worked as expected I made a square frame from carton. With hot glue I glued the motors to the bottom of the frame attached the wheels and glued at the back the caster wheel.


That's all.
It's not the prettiest of all the remote controlled card but remember this is only a proof of concept.

The program.


io(po,D0,0)
io(po,D1,0)
io(po,D2,0)
io(po,D4,0)
motonedir = 0
motwodir = 0
motone = 500

wprint |<body style="background-color:powderblue;">|
wprint |<H1><span style="color: 

red;">|
wprint "Motor Control<br>"
wprint "By Luc Volders"
wprint "</H1>"
wprint "Motor speed"
slider motone, 300, 1024
wprint "<br><br>"
button "Forward", [forward]
wprint "<br><br>"
button "Stop", [motonestop]
wprint "<br><br>"
button "Backwards", [backward]
wprint "<br><br>"
button "left", [leftturn]
wprint "<br><br>"
button "right", [rightturn]
wprint "<br><br>"
button "QUIT", [progend]
wait

[forward]
sliderval = motone
io(po,D0,0)
io(pwo,D1,sliderval)
io(pwo,D2,sliderval)
io(po,D4,0)
wait

[motonestop]
sliderval = motone
io(po,D0,0)
io(po,D1,0)
io(po,D2,0)
io(po,D4,0)
wait

[backward]
sliderval = motone
io(pwo,D0,sliderval)
io(po,D1,0)
io(po,D2,0)
io(pwo,D4,sliderval)
wait

[leftturn]
sliderval = motone
io(po,D0,0)
io(po,D1,0)
io(pwo,D2,sliderval)
io(po,D4,0)
wait

[rightturn]
sliderval = motone
io(po,D0,0)
io(pwo,D1,sliderval)
io(po,D2,0)
io(po,D4,0)
wait

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


The program is pretty straightforward.

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

These are the 4 IO pins that are attached to the L293D. D0 and D1 control the right motor and D2 and D4 control the left motor or vice versa depending on how you mounted them on the frame.

slider motone, 300, 1024

The slider controls the speed of the car.
The bottom and top values are chosen for my design and may vary according the frame weight etc. So adjust these for your own setup.

[forward]
sliderval = motone
io(po,D0,0)
io(pwo,D1,sliderval)
io(pwo,D2,sliderval)
io(po,D4,0)
wait

Here we see the forward movement routine. For motor 1 one of the IO pins (D0) is set to LOW and the other one is set to the PWM value determined by the slider. The same is done for the two IO pins for motor 2.

[backward]
sliderval = motone
io(pwo,D0,sliderval)
io(po,D1,0)
io(po,D2,0)
io(pwo,D4,sliderval)
wait

In the backward routine as you can see the IO pins are mirrored.


And here is how the controll will look on your PC, Phone or Tablet.

Extending the design.

This was for me just a prove of concept. Nothing can prevent you from expanding it. let me give you some clues on what you can do:

- Make a nice frame and enclosure so it looks like a real car
- Make a more ridgid frame so it can be used outdoors
- Add a Ultrasonic Sensor HC-SR04 so you can measure distance to walls etc
- Add a switch that keeps contact to the floor in the front of the car so you will know it is at the top of a stair.
- Add a switch that is pressed when the car runs into a wall so it can reverse or turn or whatever
- Add a ventilator that suck in air and you have a remote controlled vaccuum cleaner
- Add some head and tail lights
- Alter the design to make a boat
- Look at the Voice Command article ( https://lucstechblog.blogspot.nl/2016/01/voice-command.html ) and alter the software so you can give speech commands.

Till next time
Drive carefully and have fun

Luc Volders

Friday, January 25, 2019

Fritzing projects duplicated easy

For a complete index of all my stories press this text

Sometimes you use a tool for many years and suddenly you become aware of a feature that you never knew. Well that happened just to me.

If you are a faithfull reader of this blog you will have seen numerous schematics, breadboard layouts and stripboard layouts and they were all made with Fritzing. Fritzing is one of those valuable free tools that you really should check out. It is available from the Fritzing webpage where you can also find all kinds of projects: http://fritzing.org/home/

And after years of using Fritzing I just came after a feature I have never seen before and it is worth having a look.




Above you can see a breadboard layout made with Fritzing. It is from my weblog entry about controlling a led strip over wifi. You can find that entry here:
https://lucstechblog.blogspot.com/2018/04/rgb-strip-control-over-wifi-part-2.html

Now suppose you want to rebuild this layout yourself. This would give you no trouble bcause it is just a simple layout. For the sake of explanation let's do it.

What you would do is look at the screen and then place the components on the breadboard. Right ???

Yes but there is an easier way.
Load the design in Fritzing, chose print and just print it out.





After printing cut the picture with scissors and place it on the breadboard and just place the components where the picture displays them. The print Fritzing produces is real size !!!

For a simple layout like the one above this is overkill but look at the next layout.



Here things get a bit more complicated and then this will help you a lot !!!


As you can see the prints are really real size and it is easy to put the wires where they need to go. Just push them through the paper into the breadboard.

A simple trick that makes tinkering a lot easier.

However it gets better.


Look at this stripboard setup. It is from my article about controlling a led strip over wifi using an ESP-01.


If you want to reproduce it. Just print the stripboard layout from fritzing. Put it on a stripboard and place the components where the print shows them.


Just remember that with the stripboard version you need to place the print on the side where the components must be placed, not on the side where you solder the components !!!

Easy and efficient. Takes away a lot of work !!!

Till next time
Have fun.

Luc Volders

Friday, January 11, 2019

ESP - ESP Communication with WGET and MSGBRACNH

For a complete index of all my stories click this text

The general purpose of this story is a way to send data directly between ESP-8266's. So without the need of sending the data to a computer and having an other ESP retrieving it. No just direct communication between ESP's
There are many ways of communication between wifi devices. UDP is one way. And here I present you with another way.

The general line of this story may sound familiar because I have used this method before for communicating between an Android Phone/Tablet and an ESP8266

Send and Receive data with WGET and MSGBRANCH


Despite the fact that many people loathe it I am going to use my favorite ESP8266 devellopment environment for this tutorial: ESP-Basic.

ESP-Basic is very easy to use, interactive and has loads of drivers build in. Therefore it is very easy and fast to build IOT project's with it. It also is stable as I have made a thermometer with the softawre in ESP-Basic that is running non-stop from July 2017 without any flaws.

For an introduction and tutorial on ESP-Basic click here.
http://lucstechblog.blogspot.nl/2017/03/back-to-basic-basic-language-on-esp8266.html

Sending data

To send data we will use the wget command. The program is actually very simple.


 ' =================================  
 ' msg send/receive with msgbrach  
 ' and wget  
 ' sending routine  
 ' Luc Volders  
 ' http://lucstechblog.blogspot.nl/  
 ' =================================  
 cls  
 counter = 0  
 button "send it" , [sendit]  
 wait  
 
[sendit]   
 counter = counter + 1  
 tosend = "192.168.1.80/msg?data=there-you-are-"  
 tosend = tosend & str(counter)  
 wget(tosend)  
 wait  


Make sure you replace the IP number with the number your receiving ESP has. You can find the IP numbers of your ESP in your router.

I have used a variable with the name counter that is incremented every time the button is pressed. The variable is then transformed into a string as we can only send strings. The sentence that is actually send is:

there-you-are-X

With X being the number of times you clicked the button.

You might wonder why the "-"'s are placed between words. This is because this way of sending data does not send anything after a space. So I replaced all spaces with "-".

The important part is:

tosend = "192.168.1.80/msg?data=there-you-are-"

The receiving program will look for the phrase "data=" and knows that what follows this phrase is the data you are looking for. You can replace "data=" with anything you like but remember to alter it in the same phrase in the receiving program.

Receiving data

The receiving part is run on a second ESP. Obvious as we want to communicate between two or more ESP's.

 ' =================================  
 ' msg send/receive with msgbrach  
 ' and wget  
 ' receive routine  
 ' Luc Volders  
 ' http://lucstechblog.blogspot.nl/  
 ' =================================  
 cls  
 receiveddata = ""  
 memclear  
 msgbranch [getit]  
 textbox receiveddata  
 wait 
 
 [getit]  
 receiveddata = msgget("data")  
 receiveddata = replace(receiveddata , "-" , " ")  
 wait   


It can't get any simpler as this.
The program waits till it gets some data and then jump to the [getit] routine.

receiveddata = replace(receiveddata , "-" , " ")

This is the only tricky part in the whole program. This line makes sure that the "-" are transferred back into spaces. And then the vriable is placed in the textbox on the screen.

That's all folks.

Check, check !!!

Just like sending/receiving data with UDP there is a problem here. You can never be sure wether the data you are sending is actually received by the other ESP. We need a check for that.

 ' =================================  
 ' msg send/receive with msgbrach  
 ' and wget  
 ' sending routine with feedback  
 ' Luc Volders  
 ' http://lucstechblog.blogspot.nl/  
 ' =================================  
 cls  
 counter = 0  
 returntext = ""  
 msgbranch [check]  
 button "send it" , [sendit]  
 wprint "<br><br>"  
 wprint "returned text "  
 textbox returntext  
 wait 
 
 [sendit]   
 counter = counter + 1  
 tosend = "192.168.1.80/msg?data=there-you-are-"  
 tosend = tosend & "00" & str(counter)  
 a = wget(tosend)  
 wait 
 
 [check]  
 returntext = msgget("back")  
 returntext = right(returntext,3)  
 wait  


This is the sending program which has some extra routines to check wether the sended data is received well at the other side.

The program has the [sendit] button and accompanying routine for sending the data which is basically the same as in the previous send program.

The program also has a message-branch routine called [check]. What it does is basically wait till it receives some information from the other ESP8266. Whatever is received back is placed in the textbox on the screen. In this example I just take the last 3 received characters which will be the number from the variable counter but received back from the other ESP.

 ' ====================================  
 ' msg send/receive with msgbrach  
 ' and wget  
 ' receive routine with sending feedack  
 ' Luc Volders  
 ' http://lucstechblog.blogspot.nl/  
 ' ====================================  
   
 cls  
 receiveddata = ""  
   
 memclear  
 msgbranch [getit]  
 textbox receiveddata  
 wait  
   
 [getit]  
 receiveddata = msgget("data")  
 receiveddata = replace(receiveddata , "-" , " ")  
   
 'send confirmation  
 tosend = "192.168.1.75/msg?back="  
 reccounter = right(receiveddata, 3)  
 tosend = tosend & reccounter  
 a=wget(tosend)  
   
 wait  


The program for the receiving ESP is the same as the previous receive program except for some lines in the [getit] routine.

After we received the data and the "-"are replaced for spaces we are going to send back what we just received. Not everything though. We send the last 3 characters, which is the received number, back to the ESP that originally send it.
Make sure you replace the IP number with the number from the other ESP.

The sequence

When you click the button on ESP 1 the text "there-you-are-001" is send to ESP 2.

ESP 2 will filter the "-" out and sets the received text "there you are 001" in the textbox on the screen.

ESP 2 will then take the last 3 charactes of the received text "001" and sends them back to ESP 1

ESP 1 will receive the number and put it in the textbox on it's screen.

When you click the button on ESP 1 again the counter is incremented with 1 and the sequence repeats

So to actually check if the sended information is indeed received well you only have to compare the value of the counter with the value that is received back.


And this is how that looks on your screen. As you can see I opened two browser windows each pointing to the right IP adress so I have both the sending and receiving screen open and can check if everythings goes as expected.

Expansion

This is a simple example which can easily be expanded to send all kinds of sensor data like temperature, color codes, switch settings etc etc etc. Use your imagination.

Android, IFTTT and Google Home

Often we not only want to send data between ESP's but also between your Android Phone or Tablet and an ESP8266. Well like said in the intro of this story we have done that before.

Just look at these stories:

http://lucstechblog.blogspot.nl/2018/02/esp-voice-control-with-esp-basic.html

http://lucstechblog.blogspot.nl/2017/05/google-home-and-esp8266.html

In the second story we have Google Home triggering IFTTT and IFTTT will send a similar message to the receiving ESP. Adapt it to your own needs and you will have a plethora of possibillities.

Till next time
Have fun

Luc Volders

Friday, December 14, 2018

Simon part 2

For an index to all my stories click this text.

This story shows how I finished my version of the Simon Game which I described in the story you can re-read here: https://lucstechblog.blogspot.com/2018/12/simon.html

Now the game setup was finished, meaning hardware and software worked without any bugs, I started thinking about a casing for the game. I did not want to leave it as a bread-board prototype as my girlfriend liked the game and wanted to play it more often.

First step was to put all the hardware on stripboard. Well that was easy as the schematics are not complicated. Fritzing was used to document all the parts.You can find Fritzing here: http://fritzing.org/home/
I used two pieces of stripboard.




The first was used to put the buttons on.
Make sure you cut the strips below the buttos so you will have independend contacts and no short-circuit.

The second piece of stripboard was used to put the Attiny85 on as well as the resistor and capacitor for the neopixels.




Here also make sure you cut the strips below the Attiny 85 to prevent short-circuit.
Also be aware that you are looking at the top of the stripboard, being the component side. The actual strips are on the bottom side.

The neopixels were just soldered as a string with some wires between them like I showed in the Neopixel intro which you can re-read here: http://lucstechblog.blogspot.com/2015/10/neopixels-ws2812-intro.html

When the hardware was finished I could start drawing my casing. I am using Tinkercad for this . Tinkercad is outstanding for simple designs. And as I am no industrial designer my designs generally are simple. You can find Tinkercad here: https://www.tinkercad.com/#/


 

I started with a casing for the batteries. I power my Simon game from 3 AA batteries as they will last a long time. The Attiny85 does not consume much and the Neopixels are never lit all at the same time. The box is printed and the contacts are made from bended paperclips.




Next a simple box as casing that would fit the batteries and the board with the Attiny85.



In real world it looks like the picture above.



And last the lid for the box. I added an on-off switch in the power line. I just had to do some minor filing before all fitted.



And here is the end-result.

The STL files (to print your own casing) can be found on github with this link:

https://github.com/Lucvolders/Simon

Simon version 2 ???

By popular demand (meaning pressure by girlfriend) I am thinking about building version 2. This will have a speaker that will play a tone when a color is shown (or the button is pressed) and a display (read Oled .96 inch) for keeping the score. But please do not hold your breath while waiting for it.

Besides that it will be more expensive to build due to the screen and the use of a bigger microcontroller as we will need more I/O pins.



This was the last post for this year. I whish you all a happy christmass and hope to welcome you all again in good health in the new year.

Till next time
and don't waste all your time playing ;)

Luc Volders

Friday, December 7, 2018

Simon

For an index off all my stories click this text

Simon is an electronic memory game invented by Ralph H. Baer and Howard J. Morrison and was develloped and sold by Studio 54 in 1978. It took till 1980 before it was available in Europe. The original Simon is as far as I know not sold anymore but there are many derivates available.

Simon as a game is still very popular.

How does it work.




The layout (mostly in a circle) shows 4 colours. A random color lights up and you press the button with the same color. Next step is that the same color lights up followed by another random color. You press the buttons in the same sequence of the colors shown etc etc etc. The first steps are easy to remember but it gets more and more difficult as the sequence grows. It is very addictive.

You can find a version for windows here: http://www.memozor.com/other-free-memory-games-online/simon-games/simon-game
And you can find many variations for Android here: https://play.google.com/store/apps/collection/search_results_cluster_apps?clp=ggEHCgVzaW1vbg%3D%3D:S:ANO1ljIRByI

I have seen several versions of Simon on the internet so it is not like this has never done before. But I wanted to make my own version: hardware and software. And most of all it is a fun project for a rainy afternoon. Considering the total cost it could be a nice present for under the Christmas tree. And indeed you still have time to build one for Christmas.

Let's buid a simon game.

Most versions I saw on the internet are build with an Arduino Uno and use 4 pushbuttons and 4 leds. Therefore they need 8 I/O pins.
I am building my version with 4 pushbuttons and a string of neopixels. Therefore I only need 5 I/O pins.

Using my multiple buttons on I/O pins trick I could even reduce the I/O pins to 3 for the pushbuttons and 1 for the Neopixels. I will publish that trick in an upcoming story on this weblog. So keep on coming back.

For a detailed introduction on Neopixels read this story:
http://lucstechblog.blogspot.com/2015/10/neopixels-ws2812-intro.html

Hardware




The first version I build used the ESP8266 as a microcontroller programmed in Arduino.




The breadboard layout is simple. Just 4 pushbuttons connected to 4 I/O pins (D3,D5,D6 and D7) and a string of 4 neopixels connected to D8.
As you can see I used a separate power supply (USB wall socket) for the neopixels and for the ESP. In the end it proved that this was not necessary as the Wemos D1 supplies enough current through the 5Volt output (pin 5V) to drive the 4 neopixels.




Therefore this complete setup can be powered from a powerbank as the photo shows.

Software.

The software is in Arduino code and therefore can easily be ported between Arduino, Attiny85 and ESP8266 or ESP32 models. Choose whatever suits you best. The version presented here is the ESP8266 (Wemos D1 Mini) version. So adjust the pin numbers for your preferred microcontroller.


/* Simon Says by Luc Volders
 *  ESP8266 version
 *  1 = green  0,255,0
 *  2 = red 255,0,0
 *  3 = blue 0,0,255
 *  4 = yellow 255,255,0
*/


#include <Adafruit_NeoPixel.h>
#define PIXEL_PIN    D8
#define PIXEL_COUNT 7

int i = 0;
int j = 0;
int k = 0;
int found = 0;
int mustbe = 0;
int num = 0;
int playnum = 0;
int startprog = 1;
int turns = 0;
int turnarray[100];

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

void setup()
{
  randomSeed(analogRead(0));
  delay(10);
  pinMode(D3, INPUT_PULLUP); // geen 
  pinMode(D5, INPUT_PULLUP); // red
  pinMode(D6, INPUT_PULLUP); // blue
  pinMode(D7, INPUT_PULLUP); // yellow
  strip.begin();
  strip.show();
}

void loop()
{
  start();
}

void start()
{
  if (digitalRead(D3) == LOW or digitalRead(D5) == LOW or digitalRead(D6) == LOW or 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.show();
    delay (500);
    startprog = 0;
  }
  if (startprog == 1)
  {
    initprog();
  }
  if (startprog == 0)
  {
    startsequence();
  }
}

void initprog()
{
  for (i = 0; i < 4; i++)
  {
    strip.setPixelColor(0, 0, 0, 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.setPixelColor(i, 0, 255, 0);
    strip.show();
    delay(100);
  }
}

void keydetect()
{
  if (startprog == 1)
  {
    strip.setPixelColor(0, 0, 0, 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 (100);
    strip.setPixelColor(0, 0, 0, 255);
    strip.setPixelColor(1, 0, 0, 255);
    strip.setPixelColor(2, 0, 0, 255);
    strip.setPixelColor(3, 0, 0, 255);
    strip.show();
    delay (100);
    strip.setPixelColor(0, 0, 0, 0);
    strip.setPixelColor(1, 0, 0, 0);
    strip.setPixelColor(2, 0, 0, 0);
    strip.setPixelColor(3, 0, 0, 0);
  }
  startprog = 0;
  startsequence();
}


void testsequence ()
{
  for (k = 1; k <= turns; k++)
  {
    found = 0;
    do
    {
      delay(10);
    }
    while (digitalRead(D3) == HIGH && digitalRead(D5) == HIGH && digitalRead(D6) == HIGH && digitalRead(D7) == HIGH);
    mustbe = turnarray[k];

    // =========================================================================================
    // test for right button
    // =========================================================================================

    if (mustbe == 1)
    {
      if (digitalRead(D3) == LOW)
      {
        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);
        found = 1;
      }
    }

    if (mustbe == 2)
    {
      // button 2 ==> 101
      if (digitalRead(D5) == LOW)
      {
        strip.setPixelColor(0, 0, 0, 0);
        strip.setPixelColor(1, 255, 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);
        found = 1;
      }
    }

    if (mustbe == 3)
    {
      // button 3 ==> 110
      if (digitalRead(D6) == LOW)
      {
        strip.setPixelColor(0, 0, 0, 0);
        strip.setPixelColor(1, 0, 0, 0);
        strip.setPixelColor(2, 0, 0, 255);
        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);
        found = 1;
      }
    }

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

    if (found == 0) // FAULT FAULT FAULT

    {
      for (j = 1; j < 10; j++)
      {
        strip.setPixelColor(0, 255, 0, 0);
        strip.setPixelColor(1, 255, 0, 0);
        strip.setPixelColor(2, 255, 0, 0);
        strip.setPixelColor(3, 255, 0, 0);
        strip.setPixelColor(4, 0, 0, 0);
        strip.setPixelColor(5, 0, 0, 0);
        strip.setPixelColor(6, 0, 0, 0);
        strip.show();
        delay(120);
        strip.setPixelColor(0, 0, 0, 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(120);

      }
      i = 0;
      j = 0;
      k = 0;
      found = 0;
      mustbe = 0;
      num = 0;
      playnum = 0;
      startprog = 1;
      turns = 0;
      delay(1000);
      start();
    }



    // ============================================================================
    // end test right button
    // ============================================================================

    strip.setPixelColor(0, 0, 0, 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);
  }// end for i to turns
} // end void testsequence

void playsequence()
{
  for (i = 1; i <= turns; i++)
  {
    playnum = turnarray[i];
    if (playnum == 1)
    {
      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.show();
    }
    if (playnum == 2)
    {
      strip.setPixelColor(0, 0, 0, 0);
      strip.setPixelColor(1, 255, 0, 0);
      strip.setPixelColor(2, 0, 0, 0);
      strip.setPixelColor(3, 0, 0, 0);
      strip.show();
    }
    if (playnum == 3)
    {
      strip.setPixelColor(0, 0, 0, 0);
      strip.setPixelColor(1, 0, 0, 0);
      strip.setPixelColor(2, 0, 0, 255);
      strip.setPixelColor(3, 0, 0, 0);
      strip.show();
    }
    if (playnum == 4)
    {
      strip.setPixelColor(0, 0, 0, 0);
      strip.setPixelColor(1, 0, 0, 0);
      strip.setPixelColor(2, 0, 0, 0);
      strip.setPixelColor(3, 255, 255, 0);
      strip.show();
    }
    delay(1000);
    strip.setPixelColor(0, 0, 0, 0);
    strip.setPixelColor(1, 0, 0, 0);
    strip.setPixelColor(2, 0, 0, 0);
    strip.setPixelColor(3, 0, 0, 0);
    strip.show();
    delay(500);
  }
  do
  {
    delay(10);
  }
  while (digitalRead(D3) == HIGH && digitalRead(D5) == HIGH && digitalRead(D6) == HIGH && digitalRead(D7) == HIGH);
  testsequence();
}


void startsequence()
{
  /*
   *  1 = green  0,255,0
   *  2 = red 255,0,0
   *  3 = blue 0,0,255
   *  4 = yellow 255,255,0
  */
  turns = turns + 1;
  num = random (1, 5);
  turnarray[turns] = num;
  startprog = 0;
  strip.setPixelColor(0, 0, 0, 0);
  strip.setPixelColor(1, 0, 0, 0);
  strip.setPixelColor(2, 0, 0, 0);
  strip.setPixelColor(3, 0, 0, 0);
  strip.show();
  delay(500);
  playsequence();
}


Now before you start nagging: yes I know this software can very much be optimised. However in this form everyone might be able to read and understand what is happening so anyone can alter it to its own needs. Besides that, neither speed or memory space are a problem here.


Lets look at some parts of the software.

#include <Adafruit_NeoPixel.h>
#define PIXEL_PIN    D8
#define PIXEL_COUNT 4

As you can see you need the Adafruit Neopixel library. With the new Arduino IDE's it is a piece of cake to install new libraries so that should not give you any problems.

The setup starts with:
  randomSeed(analogRead(0));

Please make sure that this is indeed the first line in your program. The next lines will set the IO pins as input with a pull-up resistor. If you do not define the randomseed first you will not get a random figure.

In the start() part we wait till a key is pressed. Until that happens the Neopixels wil give a seqeunce of green pixels.
When a button is pressed all pixels will briefly be green and then one pixel will get the first random color choosen in the startsequence() routine.

When the first color has been choosen by startsequence() the program moves to playsequence() where the colors will be shown. The first time there will be just 1 color. The second time the array turnarray[] will have 2 values etc etc etc.

When the color sequence has been shown the program jumps to the testsequence() routine. There your keypresses will be chequed against the values in the array. If you pressed the correct buttons the variable turns is incremented and the program jumps to startsequence() again to pick the next random color.

This keeps repeating till you make an error.

If you make an error the testsequence() routine will notice. The routine will clear all variables and the program will start again.

Next step.

Attiny85

The ESP is a bit of overkill. No it is a lot of overkill !!!

Nowadays everything seems to be reeling around the ESP8266 and ESP32 but for small projects like this we seem to forget the Arduino and it's little broter the Attiny85. And the Attiny85 is well equipped for this project. So let's exchange the ESP8266 for an Attiny85. This microcontroller has 5 digital I/O pins and works at 8Mhz which is sufficient. 




As you can see the breadboard setup is not much different. However there is one extra feature which gives this setup an extra feature: it works on batteries !! 



So for the end result we can choose wether we want to power it using a power bank or plain AA or even AAA batteries. I was able to play Simon in this setup for several hours on just AAA batteries.
 

The software alterations are also minimal. In the program just replace the IO pin references to the Attiny references:

D3  ==> 0
D5  ==> 1
D6  ==> 2
D7  ==> 3
D8  ==> 4

Thats all !!!

How to play Simon.

A) the program starts by sequencing all neopixels in green till you press a button
B) If a button is pressed the Neopixels will all briefly light up green then dim
C) A random color is choosen
D) The program waits till you press the right button
E) When the right color button is chosen the program picks another random
color and will display the first and second after eachtother
F) The program then waits till you press in sequence the right color buttons
G) If the right sequence has been pushed the program loops back to step E and another color is added etc etc etc
H) if you pressed the wrong color button all Neopixels will flash red for several times and the program restarts.

Next stop: Stripboard layout and casing

Till then
Have fun

Luc Volders