Those tutorials don’t look so good. The first one requires you to use some 3rd-party component that the author wrote. The second one is just a table of contents (with no links!) as far as I can tell.
I tried to find a better example online, but I couldn’t. So I made one. The program below is an example program for sending and receiving bytes from the Maestro over a serial port in C on Windows. I tested it with Microsoft Visual C++ 2010 Express and also MinGW, but it should work with any compiler that lets you use windows.h.
I recommend that you try to get this to compile without modifying it. Then after you verify that it works, you can modify it to suit your needs.
–David Grayson
/* MaestroSerialExampleCWindows:
* Example program for sending and receiving bytes from the Maestro over a serial port
* in C on Windows.
*
* This program reads the position of channel 0.
* If the position is less than 6000, it sets the target to 7000.
* If the position is 6000 or more, it sets the target to 5000.
*
* If channel 0 is configured as a servo channel, the servo should move
* when you run this program (except perhaps the first time you run it).
* If channel 0 is configured as a digital output, the output should toggle
* when you run this program.
*
* All the Windows functions called by the program are documented on MSDN:
* http://msdn.microsoft.com/
*
* The error codes that this program may output are documented on MSDN:
* http://msdn.microsoft.com/en-us/library/ms681381%28v=vs.85%29.aspx
*
* The Maestro's serial commands are documented in the "Serial Interface"
* section of the Maestro user's guide:
* https://www.pololu.com/docs/0J40
*
* REQUIREMENT: The Maestro's Serial Mode must be set to "USB Dual Port"
* or "USB Chained" for this program to work.
*/
#include <stdio.h>
#include <windows.h>
/** Opens a handle to a serial port in Windows using CreateFile.
* portName: The name of the port.
* baudRate: The baud rate in bits per second.
* Returns INVALID_HANDLE_VALUE if it fails. Otherwise returns a handle to the port.
* Examples: "COM4", "\\\\.\\USBSER000", "USB#VID_1FFB&PID_0089&MI_04#6&3ad40bf600004# */
HANDLE openPort(const char * portName, unsigned int baudRate)
{
HANDLE port;
DCB commState;
BOOL success;
COMMTIMEOUTS timeouts;
/* Open the serial port. */
port = CreateFileA(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (port == INVALID_HANDLE_VALUE)
{
switch(GetLastError())
{
case ERROR_ACCESS_DENIED:
fprintf(stderr, "Error: Access denied. Try closing all other programs that are using the device.\n");
break;
case ERROR_FILE_NOT_FOUND:
fprintf(stderr, "Error: Serial port not found. "
"Make sure that \"%s\" is the right port name. "
"Try closing all programs using the device and unplugging the "
"device, or try rebooting.\n", portName);
break;
default:
fprintf(stderr, "Error: Unable to open serial port. Error code 0x%x.\n", GetLastError());
break;
}
return INVALID_HANDLE_VALUE;
}
/* Set the timeouts. */
success = GetCommTimeouts(port, &timeouts);
if (!success)
{
fprintf(stderr, "Error: Unable to get comm timeouts. Error code 0x%x.\n", GetLastError());
CloseHandle(port);
return INVALID_HANDLE_VALUE;
}
timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 1000;
timeouts.WriteTotalTimeoutMultiplier = 0;
success = SetCommTimeouts(port, &timeouts);
if (!success)
{
fprintf(stderr, "Error: Unable to set comm timeouts. Error code 0x%x.\n", GetLastError());
CloseHandle(port);
return INVALID_HANDLE_VALUE;
}
/* Set the baud rate. */
success = GetCommState(port, &commState);
if (!success)
{
fprintf(stderr, "Error: Unable to get comm state. Error code 0x%x.\n", GetLastError());
CloseHandle(port);
return INVALID_HANDLE_VALUE;
}
commState.BaudRate = baudRate;
success = SetCommState(port, &commState);
if (!success)
{
fprintf(stderr, "Error: Unable to set comm state. Error code 0x%x.\n", GetLastError());
CloseHandle(port);
return INVALID_HANDLE_VALUE;
}
/* Flush out any bytes received from the device earlier. */
success = FlushFileBuffers(port);
if (!success)
{
fprintf(stderr, "Error: Unable to flush port buffers. Error code 0x%x.\n", GetLastError());
CloseHandle(port);
return INVALID_HANDLE_VALUE;
}
return port;
}
/** Implements the Maestro's Get Position serial command.
* channel: Channel number from 0 to 23
* position: A pointer to the returned position value (for a servo channel, the units are quarter-milliseconds)
* Returns 1 on success, 0 on failure.
* For more information on this command, see the "Serial Servo Commands"
* section of the Maestro User's Guide: https://www.pololu.com/docs/0J40 */
BOOL maestroGetPosition(HANDLE port, unsigned char channel, unsigned short * position)
{
unsigned char command[2];
unsigned char response[2];
BOOL success;
DWORD bytesTransferred;
// Compose the command.
command[0] = 0x90;
command[1] = channel;
// Send the command to the device.
success = WriteFile(port, command, sizeof(command), &bytesTransferred, NULL);
if (!success)
{
fprintf(stderr, "Error: Unable to write Get Position command to serial port. Error code 0x%x.", GetLastError());
return 0;
}
if (sizeof(command) != bytesTransferred)
{
fprintf(stderr, "Error: Expected to write %d bytes but only wrote %d.", sizeof(command), bytesTransferred);
return 0;
}
// Read the response from the device.
success = ReadFile(port, response, sizeof(response), &bytesTransferred, NULL);
if (!success)
{
fprintf(stderr, "Error: Unable to read Get Position response from serial port. Error code 0x%x.", GetLastError());
return 0;
}
if (sizeof(response) != bytesTransferred)
{
fprintf(stderr, "Error: Expected to read %d bytes but only read %d (timeout). "
"Make sure the Maestro's serial mode is USB Dual Port or USB Chained.", sizeof(command), bytesTransferred);
return 0;
}
// Convert the bytes received in to a position.
*position = response[0] + 256*response[1];
return 1;
}
/** Implements the Maestro's Set Target serial command.
* channel: Channel number from 0 to 23
* target: The target value (for a servo channel, the units are quarter-milliseconds)
* Returns 1 on success, 0 on failure.
* Fore more information on this command, see the "Serial Servo Commands"
* section of the Maestro User's Guide: https://www.pololu.com/docs/0J40 */
BOOL maestroSetTarget(HANDLE port, unsigned char channel, unsigned short target)
{
unsigned char command[4];
DWORD bytesTransferred;
BOOL success;
// Compose the command.
command[0] = 0x84;
command[1] = channel;
command[2] = target & 0x7F;
command[3] = (target >> 7) & 0x7F;
// Send the command to the device.
success = WriteFile(port, command, sizeof(command), &bytesTransferred, NULL);
if (!success)
{
fprintf(stderr, "Error: Unable to write Set Target command to serial port. Error code 0x%x.", GetLastError());
return 0;
}
if (sizeof(command) != bytesTransferred)
{
fprintf(stderr, "Error: Expected to write %d bytes but only wrote %d.", sizeof(command), bytesTransferred);
return 0;
}
return 1;
}
/** This is the first function to run when the program starts. */
int main(int argc, char * argv[])
{
HANDLE port;
char * portName;
int baudRate;
BOOL success;
unsigned short target, position;
/* portName should be the name of the Maestro's Command Port (e.g. "COM4")
* as shown in your computer's Device Manager.
* Alternatively you can use \\.\USBSER000 to specify the first virtual COM
* port that uses the usbser.sys driver. This will usually be the Maestro's
* command port. */
portName = "\\\\.\\USBSER000"; // Each double slash in this source code represents one slash in the actual name.
/* Choose the baud rate (bits per second).
* If the Maestro's serial mode is USB Dual Port, this number does not matter. */
baudRate = 9600;
/* Open the Maestro's serial port. */
port = openPort(portName, baudRate);
if (port == INVALID_HANDLE_VALUE){ return -1; }
/* Get the current position of channel 0. */
success = maestroGetPosition(port, 0, &position);
if (!success){ return -1; }
printf("Current position is %d.\n", position);
/* Choose a new target based on the current position. */
target = (position < 6000) ? 7000 : 5000;
printf("Setting target to %d (%d us).\n", target, target/4);
/* Set the target of channel 0. */
success = maestroSetTarget(port, 0, target);
if (!success){ return - 1; }
/* Close the serial port so other programs can use it.
* Alternatively, you can just terminate the process (return from main). */
CloseHandle(port);
return 0;
}