Click here to Skip to main content
15,845,829 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Good evening,

I have a radio commanded quadcopter [][^]
which could be controlled via PC using a serial communication protocol.

The protocol format is a 18 byte string built as follow:

1)startstring 1: > (0x3e in hex)

2)startstring 2: * ( 0x2A)

3)startstring 3: > (0x3e in hex)

4)packet descripotr -> always 0x17

5)length of packet - lowbyte

6)length of packet - highbyte

7)pitch - low byte

8)pitch - high byte

9)roll -low byte

10)roll - high byte

11)thrust - low byte

12)thrust - high byte

13)yaw - low byte

14)yaw - high byte

15)flags -low byte --->> every single bit of this one enable the communication between serial port and a parts of my copter (epecially, an 1 in in 8th the third position from left , as 1000 0100 (0x84 in hex) enable comm via serial interface and enable thrust control through serial interface.

16)flags - high byte --> sendrate of packet

17)crc16 - high

18)crc16- low

Using a VC++ console program I made (with MS visual C++ express 2010 on windows 7 x32), I can send a correct packet, as I'm receiving a byte from the copter that is 0x19, written in the guide as the received packet descriptor.

The problem is that I can't "move" it, and I'm putting positive values for thrust and a 0x84 for flags.

I've also a testsoftware provided from Asctec that works, can start engine and increase thrust. I've a pair of .avi using a serial monitor, one of this software and one of my code, If someone would take a look they are uploaded in megaupload here:

testsoftware that works


my code, not working


I think that my problem should be some rigidities in write and read methods, I'm just sending the same packet in a while cycle.

If someone could address me to some notions. It would be a great favour!!

Thanks a lot, my program is the following:
// sendPacket.cpp : file di progetto principale.

namespace sendPacket {
#include "stdafx.h"
#include <conio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <valarray>

using namespace System;
using namespace std;
using namespace System::IO;
using namespace System::IO::Ports;
using namespace System::Threading;

//initialize flags structure (:1 means 1 bit register dimension, using bitfields)
 struct FLAGS
	 unsigned char pitch:1;
	 unsigned char roll:2;
	 unsigned char thrust:3;
	 unsigned char yaw:4;
	 unsigned char acc:5;
	 unsigned char height:6;
	 unsigned char acc_height:7;
	 unsigned char trigger:8;
	 unsigned char freq;

 //initialize command data structure to send
	//always 0x17
	unsigned char packetdescriptor;
	//pitch, roll, thrust, yaw commands. 0..4095 2048=middle
	unsigned short pitch;
	unsigned short roll;
	unsigned short thrust;
	unsigned short yaw;
	//Bit 0(0x01): Pitch control through serial interfacae enabled
	//Bit 1(0x02): Roll control through serial interface enabled
	//Bit 2(0x04): Thrust control through serial interface enabled
	//Bit 3(0x08): Yaw control through serial interface enabled
	//Bit 4(0x10): ACC-Mode on/off
	//Bit 5(0x20): Height control - on/off (only with ACC)
	//Bit 6(0x40): overwrite ACC/Height mode control
	//(0=mode selected by RC 1=mode selected by Bit 4 and 5)
	//Bit 7(0x17): Trigger Scientific status packet (triggers a response
	//with the actual scientific state)
	//Bit 8..15: sendrate of the scientific packet in 5Hz
	//(0=off;1=5Hz, 20=100Hz, 200=1kHz)
	//Scientific packet is send for three seconds max.
	//after the last command_data packet
	FLAGS flags; //insert a FLAG structure in a SCIENTIFIC_COMMANDDATA structure 


//send-data methods
void sendData_String(array<unsigned char> ^ send_data)
 StringComparer^ stringComparer = StringComparer::OrdinalIgnoreCase;
  // Create a new SerialPort object with default settings.
  SerialPort^ _serialPort = gcnew SerialPort("COM3");

  // Allow the user to set the appropriate properties.
  _serialPort->BaudRate = 9600 ;
  _serialPort->Parity = Parity::None;
  _serialPort->DataBits = 8;
  _serialPort->StopBits = StopBits::One;
  _serialPort->Handshake =Handshake::None;
  array<unsigned char> ^ received_data =gcnew array<unsigned char>(50);
  //open-send-close port
	 printf("\nsending data...\n");
		for(int ii=0;ii<=send_data->Length;ii++)
		 printf("%d", send_data[ii]);
	 printf("\nreceiving data...\n");
	 for (int ii=0;ii<=received_data->Length; ii++)
		       printf("%d", received_data[ii]);

//crc methods
unsigned short crc_update(unsigned short crc, unsigned char data)
 	data ^= (crc & 0xff);
	data ^= data << 4;
	return ((((unsigned short )data << 8) | ((crc>>8)&0xff))
	^ (unsigned char )(data >> 4) ^ ((unsigned short )data << 3));

 unsigned short crc16(void *data, unsigned short cnt)
	unsigned short crc=0xff;
	unsigned char *ptr=(unsigned char *) data;
	int i;
	for (i=0;i<cnt;i++)
	return crc;


int main(array<System::String ^> ^args)
	//initialize structs and variables
  FLAGS flags;
  SCIENTIFIC_COMMANDDATA scientific_commanddata;
	//int data;
	unsigned short crc;
	unsigned char *ptr = &(scientific_commanddata.packetdescriptor);
	//set startstring and crc low byte and high byte var
	array<unsigned char> ^ startString={'>','*','>'};
	//length calc
	unsigned short length = 0xb; //fix it becouse the struct is too long
	//length = sizeof(scientific_commanddata);
  unsigned char length_high =length>>8;
	unsigned char length_low =length&0xFF;		  

	//other SCIENTIFIC_COMMANDATA variables manually set
  scientific_commanddata.packetdescriptor = 0x17;
	scientific_commanddata.pitch= 0x04;
  scientific_commanddata.thrust=0x00; //fixed at 50

	//flags manually set 0x8C
  scientific_commanddata.flags.thrust=1; //enable motors
  scientific_commanddata.flags.freq= 4; //20 hz??

	//flags low calc
	unsigned char flags_low= ((scientific_commanddata.flags.pitch)+ (scientific_commanddata.flags.roll<<=1)+(scientific_commanddata.flags.thrust<<=2)+(scientific_commanddata.flags.yaw<<=3)
		+(scientific_commanddata.flags.acc<<=4) + (scientific_commanddata.flags.height<<=5)	+(scientific_commanddata.flags.acc_height<<=6)+(scientific_commanddata.flags.trigger<<=7)	);
	unsigned char flags_high = scientific_commanddata.flags.freq;
	//crc_low and crc_high calc	
  crc= crc16(ptr,length);
	unsigned char crc_low = crc&0xFF;
	unsigned char crc_high = crc>>8;
	//data to be sent
	array<unsigned char> ^ send_data =       {startString[0], //1
							startString[1], //2
							startString[2], //3
	//some string catched from testsoftware
	array<unsigned char> ^ send_data1 =	{72, 0x43, 0x43, 0x00, 0x0B, 0x17, 0xF0, 0x07, 76, 0x07, 0x00, 0x00, 0xF0, 0x07, 0x8C, 0x04, 0x79, 0}; 
	array <unsigned char> ^send_data2 = {0x3E, 0x2A, 0x3E, 0x00, 0x0B, 0x17, 0xF0, 0x07, 0xF0, 0x07, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x04, 0x5C, 0x3F}; 
	array <unsigned char> ^send_data3 = {0x3E, 0x2A, 0x3E, 0x00, 0x0B, 0x17, 0xF0, 0x07, 0xF0, 0x07, 0x00, 0x00, 0xF0, 0x07, 0x80, 0x04, 0xD0, 0xF3};
	array <unsigned char> ^send_data4 = {0x3E, 0x2A, 0x3E, 0x00, 0x0B, 0x17, 0x50, 0x09, 0xF0, 0x07, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x04, 0x89, 0xA9};
	printf("\nsend data starstring: %d\n", sizeof(send_data));
	int size =send_data->Length;

	 //array<unsigned char> ^ send_data1 =	{0x3E, 0x2A, 0x3E, 0x00, 0x0B, 0x80, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x50, 0xFF, 0x79, 0x53}; 
	//launch methods
Updated 7-Nov-10 9:12am
Alain Rist 7-Nov-10 14:14pm    
Removed C++ tag , added C++/CLI

1 solution

Nice toy :cool:

I see you got some software with the device. Maybe that could show you what data it is sending. Also, you can have a look what your program is sending and verify this is correct. You could easily check the data sent by using a virtual null modem. That should get you, and your helicopter, going. :-D[^]

Good luck!
Share this answer

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900