C# example
Forums:
Can someone please help me on the way in using the UltraBorg with Windows 10 IoT on my Raspberry Pi 2B, please?
I'm looking for an example on addressing the UltraBorg via C#.
I can already address the card through the I2C, but I'm having trouble with the rest of the communication.
How can I read the HC-SR04 distance or command the connected servo?
I think I'm missing a link for the different commands?
The board works with the python examples so the connections are ok, but I would like to use C#...
Thanks to anyone who can help me on the way :-)
- Log in to post comments

piborg
Mon, 02/08/2016 - 11:48
Permalink
Windows IoT C#
All you should really need to do is mimic the same I2C messages that the
UltraBorg.py
script is sending / receiving already.I can give you a couple of examples, but they are completely untested.
All of the C# code has been derived from: https://ms-iot.github.io/content/en-US/win10/samples/I2CAccelerometer.htm
Setting up the connection:
using
Windows.Devices.Enumeration;
using
Windows.Devices.I2c;
// UltraBorg Constants
const
byte I2C_ID_SERVO_USM = 0x36;
const
double
USM_US_TO_MM = 0.171500;
const
int
PWM_MIN = 2000;
// Should be a 1 ms burst, typical servo minimum
const
int
PWM_MAX = 4000;
// Should be a 2 ms burst, typical servo maximum
const
byte COMMAND_SET_PWM1 = 5;
// Set the PWM duty cycle for drive #1 (16 bit)
const
byte COMMAND_GET_FILTER_USM1 = 41;
// Get the filtered time measured by ultrasonic #1 in us (0 for no detection)
// Other constants are at the top of UltraBorg.py...
// Initialization for UltraBorg
private
void
UltraBorgInit() {
try
{
// Set the I2C address and speed
var settings =
new
I2cConnectionSettings(I2C_ID_SERVO_USM);
settings.BusSpeed = I2cBusSpeed.StandardMode;
// Try to find the UltraBorg on the I2C bus
string aqs = I2cDevice.GetDeviceSelector();
var dis = await DeviceInformation.FindAllAsync(aqs);
ubI2C = await I2cDevice.FromIdAsync(dis[0].Id, settings);
if
(ubI2C == null) {
// Cannot access the device...
return
;
}
// You will probably want to read the set limit values here, the example will assume the defaults are used
}
}
Setting the position for the first servo:
private
void
SetServoPosition1(
double
position) {
// Work out the values to send based on the limits
// We are using the defaults to keep the example simple
double
powerOut = (position + 1.0) / 2.0;
int
pwmDuty = (
int
)((powerOut * (self.PWM_MAX - self.PWM_MIN)) + self.PWM_MIN);
byte pwmDutyLow = (byte)(pwmDuty & 0xFF);
byte pwmDutyHigh = (byte)((pwmDuty >> 8) & 0xFF);
// Build the command data and send it
byte[] sendBytes =
new
byte[] {COMMAND_SET_PWM1, pwmDutyHigh, pwmDutyLow};
try
{
ubI2C.Write(sendBytes);
}
catch
(Exception ex) {
// Failed to send...
}
}
Reading the filtered distance from sensor #1:
private
double
GetDistance1() {
// Build the command data, send it and read the reply
byte[] recvBytes =
new
byte[I2C_MAX_LEN];
byte[] sendBytes =
new
byte[] {COMMAND_GET_FILTER_USM1};
try
{
ubI2C.WriteRead(sendBytes, recvBytes);
}
catch
(Exception ex) {
// Failed to read...
return
0.0;
}
// Work out the distance value
int
time_us = ((
int
)recvBytes[1] << 8) + (
int
)recvBytes[2];
if
(time_us == 65535) time_us = 0;
// Error value
return
(
double
)time_us * USM_US_TO_MM;
}
Wim Desimpel
Mon, 02/08/2016 - 22:53
Permalink
GetDistance1
Thank you for the quick reply.
I can move the servo with the SetServoPosition function,
but the ubI2C.WriteRead in GetDistance1 keeps returning FFFF?
I loop the function 50 times, but always the WriteRead returns 4x255?
The python code confirms that the USM is working and on USM port 1.
What could I be missing?
piborg
Tue, 02/09/2016 - 10:14
Permalink
UltraBorg not reading from C#
It may simply be that a slight gap is required between the write and read operations.
Usually this is handled by the remote device (UltraBorg in this case) using a method called clock streching.
Unfortunately when testing we found the Raspberry Pi did not seem to work correctly when we used clock stretching.
Try this version which splits the write and read into two operations to see if it works that way:
private
double
GetDistance1() {
// Build the command data, send it and read the reply
byte[] recvBytes =
new
byte[I2C_MAX_LEN];
byte[] sendBytes =
new
byte[] {COMMAND_GET_FILTER_USM1};
try
{
ubI2C.Write(sendBytes);
ubI2C.Read(recvBytes);
}
catch
(Exception ex) {
// Failed to read...
return
0.0;
}
// Work out the distance value
int
time_us = ((
int
)recvBytes[1] << 8) + (
int
)recvBytes[2];
if
(time_us == 65535) time_us = 0;
// Error value
return
(
double
)time_us * USM_US_TO_MM;
}
Wim Desimpel
Tue, 02/09/2016 - 22:06
Permalink
Solved
Works like a charm :-D
Thank you!!!
john.kattenhorn...
Fri, 03/04/2016 - 08:15
Permalink
This is awesome! I can't wait
This is awesome! I can't wait to explore what I can do with PiBorg hardware and Windows IoT
john.kattenhorn...
Sat, 10/28/2017 - 20:17
Permalink
Added github link to C# port of PicoBorg Rev controller code
Hi,
There's already a few people that have already said they've ported the python code to C# but I could not find any complete examples so I've started one here:
https://github.com/johnkattenhorn/picoborgrev