For my IOTCompass I need to be able to determined the direction to turn in. This can be done by passing the current and target positions to a function which can calculate a bearing. The calculation for this is approximated by the following formula as it does not take into account the wobbly shape of the earth:
Formula: | θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ ) |
where | φ1,λ1 is the start point, φ2,λ2 the end point (Δλ is the difference in longitude) |
From: https://www.movable-type.co.uk/scripts/latlong.html
This kind of maths is well within the capability of the Sphere's A7 core but to make the project a little more realistic I've decided to provide this calculation via an Azure Function
Getting going with Azure Functions
To be able to develop a function for Azure I needed to install the "Azure development workload" for Visual Studio.
I then created a new project, selected Azure Function App, selected .Net Standard 2 and a Http Trigger. A simple "Hello {name}" example was generated so I set the local.settings.json to have a valid port and I tested the function locally.
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "", "AzureWebJobsDashboard": "" }, "Host": { "LocalHttpPort": 7071, "CORS": "*" } }
There's quite a lot of information generated in the console for this simple operation, and if you are not sure of the url for your function it's shown in green.
I published the test function to the portal and checked it was published and working. From the function you can get the function URL which enables you to test the function in the cloud. So I checked that one too.
Function to take location and calc a direction
I translated the function across to C# and wrapped that with an Azure Function and tested using the local debug option.
public static double calcDirection(Coords source, Coords dest) { // From https://www.movable-type.co.uk/scripts/latlong.html var y = Math.Sin(dest.lon - source.lon) * Math.Cos(dest.lat); var x = Math.Cos(source.lat) * Math.Sin(dest.lat) - Math.Sin(source.lat) * Math.Cos(source.lat) * Math.Cos(dest.lon - source.lon); var brng = Math.Atan2(x, y); //Convert to degrees and normalise return 180 + (brng * (180 / Math.PI)); }
[FunctionName("LocationToDirection")] public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, TraceWriter log) { log.Info($"LocationToDirection called"); Coords source = new Coords(); Coords dest = new Coords(); var parseResult = parseParameters(req, out source, out dest); if (parseResult != null) return parseResult; double direction = calcDirection(source,dest); var returnObject = ResultsToJObject(source, dest, direction); return new JsonResult(returnObject); }
Calling an Azure Function from the Azure Sphere
For my initial version I'm just going to read the text result from the function, there are some CURL library examples provided with the Azure Sphere so that angle seems the best approach.
There's a couple of configuration items to set up. The app_manifest.json needs to be updated with the "AllowedConnections" to allow connection to the Azure function. The connection string for the function also needs to be slotted into the curl_easy_setopt(curlHandle, CURLOPT_URL, call.
I tested this with the "Hello" function.
https://docs.microsoft.com/en-us/azure-sphere/app-development/curl
https://github.com/Azure/azure-sphere-samples/tree/master/Samples/CurlEasyHttps/CurlEasyHttps
Next
There's a few challenging tasks still to complete.
Talking to the GPS dongle over the UART port
Controlling a stepper motor using GPIO https://docs.microsoft.com/en-us/azure-sphere/reference/applibs-reference/function-gpio-getvalue
Parsing the JSON, there seems to be a good library for this https://zserge.com/jsmn.html
Using a device twin to pass the target coordinates, function URL and code to the Azure Sphere https://docs.microsoft.com/en-us/azure-sphere/app-development/azure-iot-sample
Top Comments