ESP32 programming with Arduino on Windows

Today, I had an ESP32 development board arrive.  I have been eagerly awaiting this new ESP32 chip as from what I can understand, it has a lot more I/O pins (which you run out of pretty quickly on a ESP8266 dev board like a Wemos) with some more dedicated rs232 interfaces, and the big thing I have been waiting for – 2 cores!  This means in theory you can design your IoT code so one core can handle a web server and communications requests while the other core does time consuming work like blasting RF433 signals and the like – well, so I believe anyway..

So I ordered this chip – https://www.aliexpress.com/item/New-Wireless-module-NodeMcu-Lua-WIFI-Internet-of-Things-development-board-based-ESP8266-with-pcb-Antenna/32266249427.html?spm=2114.13010608.0.0.jnMoB6

Was around $20 delivered to me here in NZ and took just over a month to arrive.  Package turned up all OK.

So I started looking around to see how to setup my Arduino IDE to work with it, but i found a couple of guides that didn’t work so well for me and I had to play around to get it all to work.

Here are the steps I followed.

Make sure i am running Arduino IDE 1.6.12 – maybe if you have an older version, you want to upgrade.

 

Install Python – https://www.python.org/downloads/release/python-2712/ – I installed the 64 bit Windows one.
When the installer runs, all the options are selected except the bottom – Add to Windows Path option – tick this option too as it makes some of the next steps easier having Python in your system path

 

Install a tool called pyserial – https://pypi.python.org/pypi/pyserial
Download the pyserial-3.3.tar.gz file.  I used WinRAR to unzip it in to a folder off my Downloads folder.

 

Open a CMD prompt as Administrator.  Change directory (and drive) to the folder you extracted pyserial-3.3 to.

 

 

Type python setup.py install

You’ll see a whole load of guff on the screen as things get unpacked and installed.  Check through there is no errors.
Keep the CMD window open as we need it again later

.

 

Find your Arduino IDE folder – mine was at C:\Program Files (x86)\Arduino.
Go to the hardware folder, then create a new folder called espresif, then go in to that folder and create another new folder called esp32.

 

Download the Arduino-ESP32 code from https://github.com/espressif/arduino-esp32/archive/master.zip

Extract the contents of this download in to the folder you created above.  Should look like below

 

Go back to the CMD window, change directory to the folder you created above off your Arduino IDE folder.
Once your in the directory, type GET and press Enter

 

Install is complete! 

 

Testing time.

 

Open Arduino IDE.

I went to File > Examples and you should now see an ESP32 section.  I opened Wifi > Wifi Scan

 

Go to Tools and then the Boards sub menu.  Select the ESP32 Dev Module.  I checked the port was right too by plugging and unplugging the ESP32 in to my USB board and going into the Port > sub menu to see it was in there, then assigned – in my case COM6

 

I learnt two things with uploading the image to the board.  One, my trusty USB cable I have used on Wemos and other chips and things just wouldn’t work with the chip.  Once you plugged in the ESP32 board you just heard every 20 seconds or so the USB plug in/unplug sound on the PC.  I ended out swapping for a shorter more ‘robust’ looking cable and plugged in and then had no issues.  Second thing is – Hold down the BOOT button on the ESP32 dev board when uploading from Arduino IDE or the upload fails.  I know there is probably a pin to pull low (I think its pin 9 but I haven’t got to that yet) that will put the chip in to ‘flash’ mode.

 

With the BOOT button held down, press the -> Arrow in Arduino IDE to push the sketch to the chip.

This is a successful upload for me below:

 

With the sketch uploaded to the ESP32, I was away!  Open up the Serial Window and my simple WiFi Scan sketch was running and could see WLANs around me.

 

Now on to figure out what this chips can do.. I know the clever awesome people working on the Arduino stuff for the ESP32 are adding stuff all the time with more and more of the stuff we’ve come to expect on Arduino and ESP8266 chips is ported over.  I see OTA Updates and mDNS have recently been added.

I’m very keen to see a webserver running on one core/task/thread while something else can be consuming the loop () { } and holding it up if it needs to without affecting the performance of the webserver thread…  I’ve tried different ESP8266 web servers, async and interrupt tricks and queuing etc., but if your chip has to go off and do a long time operation, the web server doesn’t respond like if it was only being a web server.  When you’re working with some other IoT Gateway or bridge that is not very forgiving in its timeouts, this can make or break a design.
Or even better yet, the core threaded so you can just call tasks and let the chip assign them to the cores… this will allow for far more complex solutions without having to connect multiple micro controllers together and then talk on a bus like i2c between the chips.

The other big plus I see with these ESP32 chips from what I read is that all the pins are assignable in software, so you can make any logical pin physically route to another pin and it has more than one hardware serial TX/RX so you get hardware performance serial ports in case the ‘thing’ you are talking to is not so easily done with software serial without messing around with the standard development serial connection on RX/TX that is generally wired to the USB RS232 chip on the little dev board.

Anyway, now on to building something worthwhile with this chip and see what I can get it to do.

 

Azure DNS via PowerShell

In my working world, I recently have discovered the relatively new feature in Azure – DNS.

From my early playing round it seems great! Very fast to update and easy to control with scripting.

You will need the Azure PowerShell provider.  Very simple to get.

You basically open up PowerShell and type:

Install-Module AzureRM

And then you wait 5 mins while it gets and installs a whole bunch of stuff..

 

These two links are handy to give you insight in to how to connect and running different commands:

https://docs.microsoft.com/en-us/powershell/azureps-cmdlets-docs/

https://docs.microsoft.com/en-us/azure/dns/dns-operations-dnszones

 

 

Below is a script i wrote that that adds an A record.  It does a few checks and creates the dependent bits if they don’t exist – basically you need a resource group to put the DNS zone in, then you need a DNS zone and then you can create a record.

Couple of things to note from the script – you will want to set your location – my closest is “australiasoutheast” – you will want to find your preferred location to create your resource groups.

Second thing, I found this out by accident but very handy.. you can sign in to AzureRM and then ‘export’ your sign in details to a JSON file where the password etc is encrypted.. then in your script you can just use the Select-AzureRmProfile command and point it at the file, and it takes care of establishing a session with AzureRM.

Export your login details:

#Login - this prompts auth crenetials
Login-AzureRmAccount

#Once you are auth'd you can export your login credentials to an encrypted JSON file
Save-AzureRmProfile -Path “..\azureprofile.json”

 

Here’s the script – you can see it uses the saved credentials above:

param (
	[string] $zone,		  #eg: paultest100.com
	[string] $hostname,	  #eg: www.paultest100.com  
	[string] $address,	  #eg: 10.20.30.40
	[int] $TTL	          #eg: 3600
)

#get record from hostname - strip off the zone
$z = $hostname.Replace($zone, '').TrimEnd('.')

#create resource group name
$rgName = "MyDNSResources"

#Login
Select-AzureRmProfile -Path "..\azureprofile.json"
        
#Get Resource Group - Create if it doesn't exist
$rg = Get-AzureRmResourceGroup -Name $rgName
if ($rg -eq $null)
{
    $rg = New-AzureRmResourceGroup -Name $rgName -location "australiasoutheast"
}

#Get DNS Zone - Create if it doesn't exist
$dnsZone = Get-AzureRmDnsZone -Name $zone -ResourceGroupName $rg.ResourceGroupName
if ($dnsZone -eq $null)
{
    $dnsZone = New-AzureRmDnsZone -Name $zone -ResourceGroupName $rg.ResourceGroupName
}

#Get A record - Create if it doesn't exist
$dnsRecord = Get-AzureRmDnsRecordSet -Name $z -RecordType A -ZoneName $dnsZone.Name -ResourceGroupName $rg.ResourceGroupName
if ($dnsRecord -eq $null)
{
    #Create A Record
    New-AzureRmDnsRecordSet -Name $z -RecordType A -ZoneName $dnsZone.Name -ResourceGroupName $rg.ResourceGroupName -Ttl $TTL -DnsRecords (New-AzureRmDnsRecordConfig -IPv4Address $Address) -Overwrite -Force
}

Google Places API in C# .NET

I recently had a requirement to look in to using the Google Places API in some code i was writing.

I found this library here that made the whole thing a lot easier.

https://github.com/azizmb9494/Google-Places 

 

I ended up writing a quick C# application to test the different searches by lon/lat and by text.

Download Places –  a quick and dirty C# application that implements the API.. you’ll need to get a Google API Key to run it.

https://developers.google.com/places/web-service/get-api-key

 

Paste your key in to the app and then you can search by lon/lat, text or a combination of both

The basic guts of the code is below.  Having never had anything to do with Google API’s before, it was pretty simple to get some programmatic searching going on…

Example method using the API above:

 private async void TestGooglePlaces()
        {
            Response results;
            var placeList = new List<Place>();
            string apiKey = "your api key";

            if ((string.IsNullOrEmpty(txtLat.Text) || string.IsNullOrEmpty(txtLon.Text))) //if we dont have a lon/lat .. search txt
            {
                results = await Places.Api.TextSearch(txtQuery.Text, apiKey);
            }
            else
            {
                results = await Places.Api.SearchPlaces(Convert.ToDouble(txtLat.Text), Convert.ToDouble(txtLon.Text), txtQuery.Text, apiKey);
            }

            //add the results to placeList
            foreach (var place in results.Places)
            {
                placeList.Add(place);
            }

            //if there are more than one 'page' of results...
            while (results.Next != null)
            {
                //get the next lot of results
                results = await Places.Api.GetNext(results.Next, apiKey);

                foreach (var place in results.Places)
                {
                    placeList.Add(place);
                }
            }

            foreach (var place in placeList)
            {
                var placeDetails = await Places.Api.GetDetails(place.PlaceId, apiKey);

                //do stuff with your place and placeDetails                
                string name = place.Name;
                string address = placeDetails.Address;
                //......
            }

        }