Skip to content

Commit 54d5a32

Browse files
networkfusionjosesimoes
authored andcommitted
Added I2C GPS sample (#15)
1 parent 01ff87b commit 54d5a32

File tree

14 files changed

+447
-0
lines changed

14 files changed

+447
-0
lines changed
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

samples/I2C/GPS/README.md

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# I2C GPS sample
2+
3+
Shows how to use the [Windows.Devices.I2c](http://docs.nanoframework.net/api/Windows.Devices.I2c.html) API to read and write from/to an I2C device.
4+
In this sample we'll be using a [IES-SHIELD-GPS](https://i-groupuk.com/downloads/global-positioning-system-gps-shield-for-arduino/) GPS controller mounted on a [STM32F769I DISCOVERY](http://www.st.com/en/evaluation-tools/32f769idiscovery.html) board.
5+
6+
The sample project includes a full driver for the IES-SHIELD-GPS and IES-SHIELD-GPAM allowing you to retrieve the current date, time, longitude, latitude, heading, speed, (GPAM only: pitch and roll) from the device.
7+
8+
> **Note:** This sample is part of a large collection of nanoFramework feature samples.
9+
> If you are unfamiliar with Git and GitHub, you can download the entire collection as a
10+
> [ZIP file](https://github.com/nanoframework/Samples/archive/master.zip), but be
11+
> sure to unzip everything to access any shared dependencies.
12+
<!-- For more info on working with the ZIP file,
13+
> the samples collection, and GitHub, see [Get the UWP samples from GitHub](https://aka.ms/ovu2uq).
14+
> For more samples, see the [Samples portal](https://aka.ms/winsamples) on the Windows Dev Center. -->
15+
16+
17+
## Hardware requirements
18+
19+
An [STM32F769II DISCOVERY](http://www.st.com/en/evaluation-tools/32f769idiscovery.html) board.
20+
The code sample is demonstrative of the use of the I2C API.
21+
22+
23+
## Related topics
24+
25+
### Samples
26+
27+
[I2C sample](/I2C)
28+
29+
### Reference
30+
31+
[Windows.Devices.I2c](http://docs.nanoframework.net/api/Windows.Devices.I2c.html)
32+
33+
<!-- [nanoFramework app samples]() -->
34+
35+
## System requirements
36+
37+
**Client:** Windows 10
38+
39+
## Build the sample
40+
41+
1. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with the sample you want to build.
42+
2. Start Microsoft Visual Studio 2017 and select **File** \> **Open** \> **Project/Solution**.
43+
3. Starting in the folder where you unzipped the samples, go to the subfolder for this specific sample. Double-click the Visual Studio Solution (.sln) file.
44+
4. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
45+
46+
## Run the sample
47+
48+
The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
49+
50+
### Deploying the sample
51+
52+
- Select Build > Deploy Solution.
53+
54+
### Deploying and running the sample
55+
56+
- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.28922.388
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nfGPSTest", "nanoframework.Samples.GPS\nanoframework.Samples.GPS.nfproj", "{0C999724-B003-4ED6-B5AA-AC857759380B}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{0C999724-B003-4ED6-B5AA-AC857759380B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{0C999724-B003-4ED6-B5AA-AC857759380B}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{0C999724-B003-4ED6-B5AA-AC857759380B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
17+
{0C999724-B003-4ED6-B5AA-AC857759380B}.Release|Any CPU.ActiveCfg = Release|Any CPU
18+
{0C999724-B003-4ED6-B5AA-AC857759380B}.Release|Any CPU.Build.0 = Release|Any CPU
19+
{0C999724-B003-4ED6-B5AA-AC857759380B}.Release|Any CPU.Deploy.0 = Release|Any CPU
20+
EndGlobalSection
21+
GlobalSection(SolutionProperties) = preSolution
22+
HideSolutionNode = FALSE
23+
EndGlobalSection
24+
GlobalSection(ExtensibilityGlobals) = postSolution
25+
SolutionGuid = {56B4490A-E72E-459C-86A5-61E041B57DA7}
26+
EndGlobalSection
27+
EndGlobal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
using System;
2+
using System.Text;
3+
using Windows.Devices.I2c;
4+
5+
namespace nanoframework.Drivers.GPS
6+
{
7+
public class IesShieldGps
8+
{
9+
private readonly int _address;
10+
private I2cDevice _gpsController;
11+
public const byte GPAM_DEFAULT_ADDDRESS = 0x68; // GPM I2C Register
12+
13+
/// <summary>
14+
/// I2C address of the IES-SHIELD-GPS device.
15+
/// </summary>
16+
public int Address => _address;
17+
18+
/// <summary>
19+
/// Creates a driver for the IES-SHIELD-GPS.
20+
/// </summary>
21+
/// <param name="i2cBus">The I2C bus where the device is connected to.</param>
22+
/// <param name="address">The I2C address of the device.</param>
23+
public IesShieldGps(string i2cBus, int address = GPAM_DEFAULT_ADDDRESS)
24+
{
25+
// store I2C address
26+
_address = address;
27+
28+
// instantiate I2C controller
29+
_gpsController = I2cDevice.FromId(i2cBus, new I2cConnectionSettings(address)
30+
{
31+
BusSpeed = I2cBusSpeed.FastMode,
32+
SharingMode = I2cSharingMode.Shared
33+
});
34+
}
35+
36+
/// <summary>
37+
/// Gets the current pitch of the device
38+
/// </summary>
39+
/// <returns>the pitch</returns>
40+
public int GetPitch()
41+
{
42+
int pitch = 0;
43+
byte data = (byte)GetSingleRegister(63); // Read Pitch registers from GPM
44+
if ((data & 0x80) != 0)
45+
{ // If negative :
46+
47+
data &= 0x7F;
48+
pitch = (int)data;
49+
pitch *= -1; // Convert to minus value
50+
}
51+
else
52+
{
53+
pitch = (int)data;
54+
}
55+
56+
return pitch;
57+
}
58+
59+
/// <summary>
60+
/// Gets the current roll of the device
61+
/// </summary>
62+
/// <returns>the roll</returns>
63+
public int GetRoll()
64+
{
65+
int roll = 0;
66+
byte data = (byte)GetSingleRegister(64); // Read Roll registers from GPM
67+
if ((data & 0x80) != 0)
68+
{ // If negative :
69+
data &= 0x7F;
70+
roll = (int)data;
71+
roll *= -1; // convert to minus value
72+
}
73+
else
74+
{
75+
roll = (int)data;
76+
}
77+
78+
return roll;
79+
}
80+
81+
/// <summary>
82+
/// Gets the current heading of the device
83+
/// </summary>
84+
/// <returns>the heading in degrees</returns>
85+
public float GetHeading()
86+
{
87+
var heading = (float)GetSingleRegister(44) * 100;
88+
heading += (float)GetSingleRegister(45) * 10;
89+
heading += (float)GetSingleRegister(46);
90+
heading += (float)GetSingleRegister(47) / 10;
91+
return heading;
92+
}
93+
94+
/// <summary>
95+
/// Gets the current speed from the device
96+
/// </summary>
97+
/// <returns>the speed in metres per second</returns>
98+
public float GetSpeed()
99+
{
100+
var speed = (float)GetSingleRegister(52) * 100;
101+
speed += (float)GetSingleRegister(53) * 10;
102+
speed += (float)GetSingleRegister(54);
103+
speed += (float)GetSingleRegister(55) / 10;
104+
return speed;
105+
}
106+
107+
/// <summary>
108+
/// Gets the current longitude from the device
109+
/// </summary>
110+
/// <returns>the longitude in degrees</returns>
111+
public float GetLongitude()
112+
{
113+
var longitude_degrees = GetSingleRegister(23) * 100;
114+
longitude_degrees += GetDoubleRegister(24);
115+
float longitude_minutes = GetDoubleRegister(26);
116+
float longitude_seconds = (float)GetSingleRegister(28) / 10;
117+
longitude_seconds += (float)GetSingleRegister(29) / 100;
118+
longitude_seconds += (float)GetSingleRegister(30) / 1000;
119+
longitude_seconds += (float)GetSingleRegister(31) / 10000;
120+
var longitude_direction = (char)GetSingleRegister(32);
121+
122+
return ConvertDegreeAngleToFloat(longitude_degrees, longitude_minutes, longitude_seconds, longitude_direction);
123+
}
124+
125+
/// <summary>
126+
/// Gets the current latitude from the device
127+
/// </summary>
128+
/// <returns>the latitude in degrees</returns>
129+
public float GetLatitude()
130+
{
131+
132+
var latitude_degrees = GetDoubleRegister(14);
133+
float latitude_minutes = GetDoubleRegister(16);
134+
float latitude_seconds = (float)GetSingleRegister(18) / 10;
135+
latitude_seconds += (float)GetSingleRegister(19) / 100;
136+
latitude_seconds += (float)GetSingleRegister(20) / 1000;
137+
latitude_seconds += (float)GetSingleRegister(21) / 10000;
138+
var latitude_direction = (char)GetSingleRegister(22);
139+
140+
return ConvertDegreeAngleToFloat(latitude_degrees, latitude_minutes, latitude_seconds, latitude_direction);
141+
}
142+
143+
/// <summary>
144+
/// Gets the current Date and Time from the device
145+
/// </summary>
146+
/// <returns>Current DateTime</returns>
147+
public DateTime GetDateTime()
148+
{
149+
var y1 = GetDoubleRegister(10); //Read Year 1 registers from GPM and print to PC
150+
var y2 = GetDoubleRegister(12); //Read Year 2 registers from GPM and print to PC
151+
var mo = GetDoubleRegister(8); //Read Month registers from GPM and print to PC
152+
var d = GetDoubleRegister(6); //Read Day registers from GPM and print to PC
153+
154+
var hh = GetDoubleRegister(0); //Read Hours registers from GPM and print to PC
155+
var mm = GetDoubleRegister(2); //Read Minutes registers from GPM and print to PC
156+
var ss = GetDoubleRegister(4); //Read Seconds registers from GPM and print to PC
157+
158+
var yy = (y1 * 100) + y2;
159+
160+
if (yy != 0 && mo != 0 && d != 0 && hh <= 24 && mm <= 59 && ss <= 59) //sanity check, otherwise the parse could fail
161+
{
162+
return new DateTime(yy, mo, d, hh, mm, ss);
163+
}
164+
else
165+
{
166+
return new DateTime();
167+
}
168+
}
169+
170+
/// <summary>
171+
/// Converts DMS to DD
172+
/// </summary>
173+
/// <param name="degrees"></param>
174+
/// <param name="minutes"></param>
175+
/// <param name="seconds"></param>
176+
/// <param name="direction"></param>
177+
/// <returns></returns>
178+
private float ConvertDegreeAngleToFloat(float degrees, float minutes, float seconds, char direction)
179+
{
180+
//Example: 17.21.18S
181+
182+
var multiplier = ((direction == 'S') || (direction == 'W')) ? -1 : 1; //handle south and west
183+
184+
return (degrees + (minutes / 60) + (seconds / 3600)) * multiplier;
185+
}
186+
187+
/// <summary>
188+
/// Get double register value from GPAM
189+
/// </summary>
190+
/// <param name="register">The register to get</param>
191+
/// <returns></returns>
192+
private int GetDoubleRegister(byte register)
193+
{
194+
195+
byte[] highByte = new byte[1];
196+
byte[] lowByte = new byte[1];
197+
198+
_gpsController.Write(new byte[] { register });
199+
_gpsController.Read(highByte);
200+
201+
_gpsController.Write(new byte[] { register += 1 });
202+
_gpsController.Read(lowByte);
203+
204+
int value = (highByte[0] * 10) + lowByte[0];
205+
return (value);
206+
}
207+
208+
/// <summary>
209+
/// Get single register value from GPAM
210+
/// </summary>
211+
/// <param name="register">The register to get</param>
212+
/// <returns></returns>
213+
private int GetSingleRegister(byte register)
214+
{
215+
216+
byte[] buffer = new byte[1];
217+
_gpsController.Write(new byte[] { register });
218+
_gpsController.Read(buffer);
219+
return (buffer[0]);
220+
}
221+
}
222+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Threading;
4+
using nanoframework.Drivers.GPS;
5+
6+
namespace nanoframework.Samples.GPS
7+
{
8+
public class Program
9+
{
10+
11+
public static void Main()
12+
{
13+
//Configured for use on the STM32F769I-Discovery
14+
//NOTE:- this shield is not pin compatible and must be wired as follows:
15+
//SDA = CN9 PIN D14
16+
//SDC = CN9 PIN D15
17+
//VIN = CN11 PIN 5 (5V)
18+
//GND = CN11 PIN 6 (GND)
19+
IesShieldGps gps = new IesShieldGps("I2C1", 0x68);
20+
21+
Console.WriteLine("Application started...awaiting GPS and Acceleration data..");
22+
23+
Thread.Sleep(3000); // Wait 3 seconds for DS-GPAM to initialise
24+
25+
for ( ; ; )
26+
{
27+
for (int x = 0; x <= 29; x++)
28+
{
29+
Console.WriteLine(gps.GetDateTime().ToString("u"));
30+
Thread.Sleep(1000);
31+
}
32+
33+
Console.Write("Latitude: ");
34+
Console.WriteLine(gps.GetLatitude().ToString("N6"));
35+
36+
Console.Write("Longitude: ");
37+
Console.WriteLine(gps.GetLongitude().ToString("N6"));
38+
39+
Console.Write("Heading: ");
40+
Console.WriteLine(gps.GetHeading().ToString("N2"));
41+
42+
Console.Write("Speed: ");
43+
Console.WriteLine(gps.GetSpeed().ToString("N2"));
44+
45+
Console.Write("Pitch: ");
46+
Console.WriteLine(gps.GetPitch().ToString());
47+
48+
Console.Write("Roll:");
49+
Console.WriteLine(gps.GetRoll().ToString());
50+
}
51+
52+
//Thread.Sleep(Timeout.Infinite);
53+
}
54+
}
55+
}
56+
57+
58+

0 commit comments

Comments
 (0)