The original remote control that comes with the helicopter is pretty good, at least a lot easier to use than a touchscreen.
However, our passion doesn't end here with mere manual control. Inspired by all those robodance projects, we need more joy of robotic automation.
Let's hack the SYMA S107 helicopter to give it some artificial intelligence!
You might wonder why this particular model (Syma S107)? Well, simply because it is perhaps the most popular one in the IR helicopter market. And many brilliant hackers have already done the work for us. We don't have to reinvent the wheel to hack it again.
As usual, let's start with an Arduino, the most simple way to prototype electronic projects. Our goal here is to make an arduino based IR transmitter to programmatically control the helicopter.
Step 1. Prepare the circuit
The circuit is extremely simple, we just need:
1 Arduino, 1 IR LED and 1 resister of 200 to 1000 ohm.
Optional: an IR receiver (for testing).
That's all to transmit IR signal from Arduino to the helicopter. If you already have an Arduino board, it costs you almost nothing to get the rest parts.
If you are interested in IR tests, here is a detailed tutorial: http://www.ladyada.net/learn/sensors/ir.html
Otherwise, we can directly load the Arduino code and control the helicopter!
Step 2. Program the Arduino
Fortunately, there are several existing Arduino projects we can directly use and customize.
The first working code (tested):
//Arduino code to control a helicotper. int IRledPin = 12; int incomingByte = 0; String incomingString; int pulseValues[33]; int pulseLength = 0; void setup() { // initialize the IR digital pin as an output: pinMode(IRledPin, OUTPUT); pinMode(13, OUTPUT); Serial.begin(9600); for (int i=0; i < 13; i++) pulseValues[i] = 0; } void loop() { SendCode(); } void pulseIR(long microsecs) { cli(); // this turns off any background interrupts while (microsecs > 0) { // 38 kHz is about 13 microseconds high and 13 microseconds low digitalWrite(IRledPin, HIGH); // this takes about 3 microseconds to happen delayMicroseconds(10); // hang out for 10 microseconds digitalWrite(IRledPin, LOW); // this also takes about 3 microseconds delayMicroseconds(10); // hang out for 10 microseconds // so 26 microseconds altogether microsecs -= 26; } sei(); // this turns them back on } void Zero() { pulseIR(300); delayMicroseconds(300); pulseLength += 600; } void One() { pulseIR(300); delayMicroseconds(600); pulseLength += 900; } void sendPulseValue(int pulseValue) { if (pulseValue == 1) One(); else Zero(); } void checkPulseChanges() { if (Serial.available() > 0) { incomingByte = Serial.read(); //Pulse 1 if (incomingByte == 'a') pulseValues[0] = 0; if (incomingByte == 'A') pulseValues[0] = 1; //Pulse 2 if (incomingByte == 'b') pulseValues[1] = 0; if (incomingByte =='B') pulseValues[1] = 1; //Pulse 3 if (incomingByte == 'c') pulseValues[2] = 0; if (incomingByte == 'C') pulseValues[2] = 1; //Pulse 4 if (incomingByte == 'd') pulseValues[3] = 0; if (incomingByte == 'D') pulseValues[3] = 1; //Pulse 5 if (incomingByte == 'e') pulseValues[4] = 0; if (incomingByte == 'E') pulseValues[4] = 1; //Pulse 6 if (incomingByte == 'f') pulseValues[5] = 0; if (incomingByte == 'F') pulseValues[5] = 1; //Pulse 7 if (incomingByte == 'g') pulseValues[6] = 0; if (incomingByte == 'G') pulseValues[6] = 1; //Pulse 8 if (incomingByte == 'h') pulseValues[7] = 0; if (incomingByte == 'H') pulseValues[7] = 1; //Pulse 9 if (incomingByte == 'i') pulseValues[8] = 0; if (incomingByte == 'I') pulseValues[8] = 1; //Pulse 10 if (incomingByte == 'j') pulseValues[9] = 0; if (incomingByte == 'J') pulseValues[9] = 1; //Pulse 11 if (incomingByte == 'k') pulseValues[10] = 0; if (incomingByte == 'K') pulseValues[10] = 1; //Pulse 12 if (incomingByte == 'l') pulseValues[11] = 0; if (incomingByte == 'L') pulseValues[11] = 1; //Pulse 13 if (incomingByte == 'm') pulseValues[12] = 0; if (incomingByte == 'M') pulseValues[12] = 1; //Pulse 14 if (incomingByte == 'o') pulseValues[13] = 0; if (incomingByte == 'O') pulseValues[13] = 1; //Pulse 15 if (incomingByte == 'p') pulseValues[14] = 0; if (incomingByte == 'P') pulseValues[14] = 1; //Pulse 16 if (incomingByte == 'q') pulseValues[15] = 0; if (incomingByte == 'Q') pulseValues[15] = 1; //Pulse 17 if (incomingByte == 'r') pulseValues[16] = 0; if (incomingByte == 'R') pulseValues[16] = 1; //Pulse 18 if (incomingByte == 's') pulseValues[17] = 0; if (incomingByte == 'S') pulseValues[17] = 1; //Pulse 19 if (incomingByte == 't') pulseValues[18] = 0; if (incomingByte == 'T') pulseValues[18] = 1; //Pulse 20 if (incomingByte == 'u') pulseValues[19] = 0; if (incomingByte == 'U') pulseValues[19] = 1; //Pulse 21 if (incomingByte == 'v') pulseValues[20] = 0; if (incomingByte == 'V') pulseValues[20] = 1; //Pulse 22 if (incomingByte == 'w') pulseValues[21] = 0; if (incomingByte == 'W') pulseValues[21] = 1; //Pulse 23 if (incomingByte == 'x') pulseValues[22] = 0; if (incomingByte == 'X') pulseValues[22] = 1; //Pulse 24 if (incomingByte == 'y') pulseValues[23] = 0; if (incomingByte == 'Y') pulseValues[23] = 1; //Pulse 25 if (incomingByte == 'z') pulseValues[24] = 0; if (incomingByte == 'Z') pulseValues[24] = 1; //Pulse 26 if (incomingByte == '1') pulseValues[25] = 0; if (incomingByte == '2') pulseValues[25] = 1; //Pulse 27 if (incomingByte == '3') pulseValues[26] = 0; if (incomingByte == '4') pulseValues[26] = 1; //Pulse 28 if (incomingByte == '5') pulseValues[27] = 0; if (incomingByte == '6') pulseValues[27] = 1; //Pulse 29 if (incomingByte == '7') pulseValues[28] = 0; if (incomingByte == '8') pulseValues[28] = 1; //Pulse 30 if (incomingByte == '9') pulseValues[29] = 0; if (incomingByte == '!') pulseValues[29] = 1; //Pulse 31 if (incomingByte == '@') pulseValues[30] = 0; if (incomingByte == '#') pulseValues[30] = 1; //Pulse 32 if (incomingByte == '$') pulseValues[31] = 0; if (incomingByte == '%') pulseValues[31] = 1; //Pulse 33 if (incomingByte == '^') pulseValues[32] = 0; if (incomingByte == '&') pulseValues[32] = 1; } } void SendCode() { while (true) { checkPulseChanges(); pulseIR(4000); delayMicroseconds(2000); pulseLength=6000; sendPulseValue(pulseValues[0]); sendPulseValue(pulseValues[1]); sendPulseValue(pulseValues[2]); sendPulseValue(pulseValues[3]); sendPulseValue(pulseValues[4]); sendPulseValue(pulseValues[5]); sendPulseValue(pulseValues[6]); sendPulseValue(pulseValues[7]); sendPulseValue(pulseValues[8]); sendPulseValue(pulseValues[9]); sendPulseValue(pulseValues[10]); sendPulseValue(pulseValues[11]); sendPulseValue(pulseValues[12]); sendPulseValue(pulseValues[13]); sendPulseValue(pulseValues[14]); sendPulseValue(pulseValues[15]); sendPulseValue(pulseValues[16]); sendPulseValue(pulseValues[17]); sendPulseValue(pulseValues[18]); sendPulseValue(pulseValues[19]); sendPulseValue(pulseValues[20]); sendPulseValue(pulseValues[21]); sendPulseValue(pulseValues[22]); sendPulseValue(pulseValues[23]); sendPulseValue(pulseValues[24]); sendPulseValue(pulseValues[25]); sendPulseValue(pulseValues[26]); sendPulseValue(pulseValues[27]); sendPulseValue(pulseValues[28]); sendPulseValue(pulseValues[29]); sendPulseValue(pulseValues[30]); sendPulseValue(pulseValues[31]); //Footer pulseIR(360); delayMicroseconds( (28600 - pulseLength) ); } }
This is the processing code to control the helicopter using the PC's camera and mouse wheel:
import processing.serial.*; import controlP5.*; import JMyron.*; JMyron m; ControlP5 controlP5; CheckBox checkbox; Button b; float boxX; float boxY; int boxSize = 20; boolean mouseOverBox = false; byte[] previousFlags = new byte[32]; byte[] flagsToSend = new byte[32]; Serial port; String outString; int helicopterUpSpeed = 0; int helicopterPitch = 63; int helicopterYaw = 68; void setup() { m = new JMyron(); m.start(640,480); size(640, 480); controlP5 = new ControlP5(this); checkbox = controlP5.addCheckBox("checkBox", 20, 20); // make adjustments to the layout of a checkbox. checkbox.setColorForeground(color(120)); checkbox.setColorActive(color(255)); checkbox.setColorLabel(color(128)); checkbox.setItemsPerRow(8); checkbox.setSpacingColumn(30); checkbox.setSpacingRow(10); // add items to a checkbox. checkbox.addItem("1", 0); checkbox.addItem("2", 0); checkbox.addItem("3", 0); checkbox.addItem("4", 0); checkbox.addItem("5", 0); checkbox.addItem("6", 0); checkbox.addItem("7", 0); checkbox.addItem("8", 0); checkbox.addItem("9", 0); checkbox.addItem("10", 0); checkbox.addItem("11", 0); checkbox.addItem("12", 0); checkbox.addItem("13", 0); checkbox.addItem("14", 0); checkbox.addItem("15", 0); checkbox.addItem("16", 0); checkbox.addItem("17", 0); checkbox.addItem("18", 0); checkbox.addItem("19", 0); checkbox.addItem("20", 0); checkbox.addItem("21", 0); checkbox.addItem("22", 0); checkbox.addItem("23", 0); checkbox.addItem("24", 0); checkbox.addItem("25", 0); checkbox.addItem("26", 0); checkbox.addItem("27", 0); checkbox.addItem("28", 0); checkbox.addItem("29", 0); checkbox.addItem("30", 0); checkbox.addItem("31", 0); checkbox.addItem("32", 0); checkbox.deactivateAll(); controlP5.addButton("Up", 0, 120, 120, 35, 20); controlP5.addButton("Down", 0, 120, 160, 35, 20); controlP5.addButton("Forward", 0, 180, 120, 45, 20); controlP5.addButton("Backward", 0, 180, 160, 45, 20); controlP5.addButton("TurnLeft", 0, 60, 120, 40, 20); controlP5.addButton("TurnRight", 0, 60, 160, 40, 20); port = new Serial(this, Serial.list()[0], 9600); for (int i=0;i<32;i++) { flagsToSend[i] = 0; previousFlags[i] = 0; } addMouseWheelListener(new java.awt.event.MouseWheelListener() { public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { mouseWheel(evt.getWheelRotation()); } } ); startSetUp(); } String addForwardZeroesTT(String inputString, int totalLength) { String outString = ""; for (int i = 0; i < (totalLength - inputString.length()); i++) outString += "0"; outString = outString + inputString; return outString; } //Incremental like bits //0000, 0001, 0010, 0011, 0100, etc void Up() { String currentSpeed = addForwardZeroesTT(binary(helicopterUpSpeed), 7); if(helicopterUpSpeed <= 125) helicopterUpSpeed += 1; String newSpeed = addForwardZeroesTT(binary(helicopterUpSpeed), 7); setNewSpeed(currentSpeed, newSpeed); } void Down() { String currentSpeed = addForwardZeroesTT(binary(helicopterUpSpeed), 7); if (helicopterUpSpeed > 0) helicopterUpSpeed -= 1; String newSpeed = addForwardZeroesTT(binary(helicopterUpSpeed), 7); setNewSpeed(currentSpeed, newSpeed); } void Backward() { String currentSpeed = addForwardZeroesTT(binary(helicopterPitch), 7); helicopterPitch += 1; String newSpeed = addForwardZeroesTT(binary(helicopterPitch), 7); setNewPitch(currentSpeed, newSpeed); } void Forward() { String currentSpeed = addForwardZeroesTT(binary(helicopterPitch), 7); helicopterPitch -= 1; String newSpeed = addForwardZeroesTT(binary(helicopterPitch), 7); setNewPitch(currentSpeed, newSpeed); } void TurnLeft() { String currentSpeed = addForwardZeroesTT(binary(helicopterYaw), 7); helicopterYaw -= 1; String newSpeed = addForwardZeroesTT(binary(helicopterYaw), 7); setNewYaw(currentSpeed, newSpeed); } void TurnRight() { String currentSpeed = addForwardZeroesTT(binary(helicopterYaw), 7); helicopterYaw += 1; String newSpeed = addForwardZeroesTT(binary(helicopterYaw), 7); setNewYaw(currentSpeed, newSpeed); } void setNewSpeed(String currentSpeed, String newSpeed) { //Compare each bit and see if it needs changing. if (newSpeed.charAt(6) != currentSpeed.charAt(6) ) checkbox.toggle(23); if (newSpeed.charAt(5) != currentSpeed.charAt(5) ) checkbox.toggle(22); if (newSpeed.charAt(4) != currentSpeed.charAt(4) ) checkbox.toggle(21); if (newSpeed.charAt(3) != currentSpeed.charAt(3) ) checkbox.toggle(20); if (newSpeed.charAt(2) != currentSpeed.charAt(2) ) checkbox.toggle(19); if (newSpeed.charAt(1) != currentSpeed.charAt(1) ) checkbox.toggle(18); if (newSpeed.charAt(0) != currentSpeed.charAt(0) ) checkbox.toggle(17); } void setNewPitch(String currentSpeed, String newSpeed) { if (newSpeed.charAt(6) != currentSpeed.charAt(6) ) checkbox.toggle(15); if (newSpeed.charAt(5) != currentSpeed.charAt(5) ) checkbox.toggle(14); if (newSpeed.charAt(4) != currentSpeed.charAt(4) ) checkbox.toggle(13); if (newSpeed.charAt(3) != currentSpeed.charAt(3) ) checkbox.toggle(12); if (newSpeed.charAt(2) != currentSpeed.charAt(2) ) checkbox.toggle(11); if (newSpeed.charAt(1) != currentSpeed.charAt(1) ) checkbox.toggle(10); if (newSpeed.charAt(0) != currentSpeed.charAt(0) ) checkbox.toggle(9); } void setNewYaw(String currentSpeed, String newSpeed) { if (newSpeed.charAt(6) != currentSpeed.charAt(6) ) checkbox.toggle(7); if (newSpeed.charAt(5) != currentSpeed.charAt(5) ) checkbox.toggle(6); if (newSpeed.charAt(4) != currentSpeed.charAt(4) ) checkbox.toggle(5); if (newSpeed.charAt(3) != currentSpeed.charAt(3) ) checkbox.toggle(4); if (newSpeed.charAt(2) != currentSpeed.charAt(2) ) checkbox.toggle(3); if (newSpeed.charAt(1) != currentSpeed.charAt(1) ) checkbox.toggle(2); if (newSpeed.charAt(0) != currentSpeed.charAt(0) ) checkbox.toggle(1); } void startSetUp() { //First clear the arduino. port.write('a'); port.write('b'); port.write('c'); port.write('d'); port.write('e'); port.write('f'); port.write('g'); port.write('h'); port.write('i'); port.write('j'); port.write('k'); port.write('l'); port.write('m'); port.write('o'); port.write('p'); port.write('q'); port.write('r'); port.write('s'); port.write('t'); port.write('u'); port.write('v'); port.write('w'); port.write('x'); port.write('y'); port.write('z'); port.write('1'); port.write('3'); port.write('5'); port.write('7'); port.write('9'); port.write('@'); port.write('$'); port.write('^'); //Set the pulse to the basic configuration. checkbox.toggle(1); checkbox.toggle(6); checkbox.toggle(10); checkbox.toggle(11); checkbox.toggle(12); checkbox.toggle(13); checkbox.toggle(14); checkbox.toggle(15); checkbox.toggle(16); checkbox.toggle(25); checkbox.toggle(28); checkbox.toggle(29); checkbox.toggle(30); } void draw() { background(200); m.update(); int[] img = m.image(); //first draw the camera view onto the screen loadPixels(); for(int i=0;i<640*480;i++){ pixels[i] = img[i]; } updatePixels(); noFill(); int[][] a; CheckHelicopterPosition(); text(" Current Speed: " + helicopterUpSpeed, 230, 135); text(" Pitch: " + helicopterPitch, 230, 165); text(" Yaw: " + helicopterYaw, 230, 195); } void CheckHelicopterPosition() { noFill(); int[][] a; m.trackColor(255,255,0,255); //draw bounding boxes of globs a = m.globBoxes(); stroke(255,0,0); int averageY = 0; for(int i=0;i<a.length;i++){ int[] b = a[i]; rect(b[0], b[1], b[2], b[3]); averageY += b[1]; } if (a.length > 0) { averageY = averageY / a.length; line(0,averageY,640,averageY); text(" Average Y: " + averageY, 230, 215); if (averageY > 240) { text(" Action: up ", 350, 20); delay(150); //Up(); } else { text(" Action down ", 350,20); //delay(250); //Down(); } } } void controlEvent(ControlEvent theEvent) { if (theEvent.isGroup()) { for (int i=0;i<theEvent.group().arrayValue().length;i++) { byte n = (byte)theEvent.group().arrayValue()[i]; flagsToSend[i] = n; //there was a change in the flags, send the update. if (previousFlags[i] != flagsToSend[i]) { println(i); if (i==0) { if (n == 0) { port.write('a'); } else { port.write('A'); } } if (i==1) { if (n == 0) { port.write('b'); } else { port.write('B'); } } if (i==2) { if (n == 0) { port.write('c'); } else { port.write('C'); } } if (i==3) { if (n == 0) { port.write('d'); } else { port.write('D'); } } if (i==4) { if (n == 0) { port.write('e'); } else { port.write('E'); } } if (i==5) { if (n == 0) { port.write('f'); } else { port.write('F'); } } if (i==6) { if (n == 0) { port.write('g'); } else { port.write('G'); } } if (i==7) { if (n == 0) { port.write('h'); } else { port.write('H'); } } if (i==8) { if (n == 0) { port.write('i'); } else { port.write('I'); } } if (i==9) { if (n == 0) { port.write('j'); } else { port.write('J'); } } if (i==10) { if (n == 0) { port.write('k'); } else { port.write('K'); } } if (i==11) { if (n == 0) { port.write('l'); } else { port.write('L'); } } if (i==12) { if (n == 0) { port.write('m'); } else { port.write('M'); } } if (i==13) { if (n == 0) { port.write('o'); } else { port.write('O'); } } if (i==14) { if (n == 0) { port.write('p'); } else { port.write('P'); } } if (i==15) { if (n == 0) { port.write('q'); } else { port.write('Q'); } } if (i==16) { if (n == 0) { port.write('r'); } else { port.write('R'); } } if (i==17) { if (n == 0) { port.write('s'); } else { port.write('S'); } } if (i==18) { if (n == 0) { port.write('t'); } else { port.write('T'); } } if (i==19) { if (n == 0) { port.write('u'); } else { port.write('U'); } } if (i==20) { if (n == 0) { port.write('v'); } else { port.write('V'); } } if (i==21) { if (n == 0) { port.write('w'); } else { port.write('W'); } } if (i==22) { if (n == 0) { port.write('x'); } else { port.write('X'); } } if (i==23) { if (n == 0) { port.write('y'); } else { port.write('Y'); } } if (i==24) { if (n == 0) { port.write('z'); } else { port.write('Z'); } } if (i==25) { if (n == 0) { port.write('1'); } else { port.write('2'); } } if (i==26) { if (n == 0) { port.write('3'); } else { port.write('4'); } } if (i==27) { if (n == 0) { port.write('5'); } else { port.write('6'); } } if (i==28) { if (n == 0) { port.write('7'); } else { port.write('8'); } } if (i==29) { if (n == 0) { port.write('9'); } else { port.write('!'); } } if (i==30) { if (n == 0) { port.write('@'); } else { port.write('#'); } } if (i==31) { if (n == 0) { port.write('$'); } else { port.write('%'); } } if (i==32) { if (n == 0) { port.write('^'); } else { port.write('&'); } } } previousFlags[i]=n; } } } void mouseWheel(int delta) { if (delta == 1) Down(); else Up(); }We have tested it. It worked like a charm. Exactly as the project creator says:
"Utilizing the input from the webcam, it adjusts the speed until the helicopter is in the middle of the screen.
If it goes too high, it lowers the speed. If it gets too low or is stopped, it slowly increases the upwards speed."
For more details on this project, please have a glance here: http://www.avergottini.com/2011/05/arduino-helicopter-infrared-controller.html
The second working code (not yet tested by DIY Phone Gadgets):
Of course, your SYMA S107 helicopter might not always be exactly the same as others'. The first code might not work for your helicopter. Don't worry, it is possible that you have a 3-channel (30-bit) version, which uses a different protocol. Just load the following Arduino code:
/* S107 3-channel with checksum helicopter control code * Copyright (C) 2012, Andrew Barry, Dan Barry * * Uses an Arduino to control a S107 helicopter * * * Instructions: * Connect an IR LED array to pin 8 (using a FET to amplify the signal) * and use the serial monitor to send commands to the system * */ #define LED 8 #define STATUS 13 //#define TAKEOFF_THROTTLE 240 //#define HOLDING_THROTTLE 130 byte yawCmd, pitchCmd, throttleCmd, trimCmd; // Set this value for the default channel // A = 0 // B = 1 // C = 2 byte channel = 0; /* * Setup function that initializes the serial port and * sets some default values for the control variables. * Also sets up the pins we'll be using. */ void setup() { Serial.begin(9600); pinMode(STATUS,OUTPUT); digitalWrite(STATUS,LOW); pinMode(LED,OUTPUT); digitalWrite(LED,LOW); yawCmd = 8; pitchCmd = 8; trimCmd = 0; throttleCmd = 0; Serial.println("throttle = 0, standing by for commands."); } /* * Function that does the actual work of converting commands into * IR LED pulses and changes the pins in the appropriate manner. */ byte sendPacket(byte yaw, byte pitch, byte throttle, byte trim) { int packetData[100]; int pulseNum; digitalWrite(STATUS,HIGH); float channelDelayValue = 136500; // channel A B or C // A is 10 with 136500us packet delay // B is 01 with 105200us packet delay // C is 11 with 168700us packet delay if (channel == 0) { packetData[0] = 1; packetData[1] = 0; channelDelayValue = 136500; } else if (channel == 1) { packetData[0] = 0; packetData[1] = 1; channelDelayValue = 105200; } else { packetData[0] = 1; packetData[1] = 1; channelDelayValue = 168700; } packetData[2] = 0; packetData[3] = 0; // pitch packetData[7] = (pitch & 0b1000) >> 3; // direction bit if (pitch < 8) { pitch = 8 - pitch; } packetData[6] = (pitch & 0b0100) >> 2; // others are speed bits, note that they are reversed packetData[5] = (pitch & 0b0010) >> 1; packetData[4] = (pitch & 0b0001); // throttle // bits are reversed in the throttle command packetData[15] = (throttle & 0b10000000) >> 7; packetData[14] = (throttle & 0b01000000) >> 6; packetData[13] = (throttle & 0b00100000) >> 5; packetData[12] = (throttle & 0b00010000) >> 4; packetData[11] = (throttle & 0b00001000) >> 3; packetData[10] = (throttle & 0b00000100) >> 2; packetData[9] = (throttle & 0b00000010) >> 1; packetData[8] = (throttle & 0b00000001); // yaw packetData[19] = (yaw & 0b1000) >> 3; // direction bit if (yaw < 8) { yaw = 8 - yaw; } packetData[18] = (yaw & 0b0100) >> 2; packetData[17] = (yaw & 0b0010) >> 1; packetData[16] = (yaw & 0b0001); // these 4 bits are the checksum, so make sure they // are 0s so they don't change the XOR later on packetData[20] = 0; packetData[21] = 0; packetData[22] = 0; packetData[23] = 0; // yaw trim / yaw adjust (the little dial on the controller) // 6 bits packetData[24] = 0; packetData[25] = 0; packetData[26] = 0; packetData[27] = 0; packetData[28] = 0; packetData[29] = 0; // these bits are never sent but we do the checksum // computation in 4-bit chunks, with the trailing two // bits set to zero, so we set them to zero here to make // the checksum a bit easier to compute packetData[30] = 0; packetData[31] = 0; int i; int checksum[10]; checksum[0] = 0; checksum[1] = 0; checksum[2] = 0; checksum[3] = 0; // compute checksum -- bitwise XOR of 4-bit chunks // with two zeros padding the *end* of the last two bits for (i=0; i 0) { if (Serial.available() == true) { Serial.println("HOLD ABORTED"); break; } packetDelay = sendPacket(yawIn, pitchIn, throttleIn, trimCmd); delayTime = delayTime - packetDelay; delay(packetDelay); delay(delayAmount); delayTime = delayTime - delayAmount; } Serial.println("Done holding."); } void Land() { static int i; Serial.println("Landing"); for(i=throttleCmd;i>0;i--){ HoldCommand(8,8,throttleCmd,50); } throttleCmd = 0; } /* * Function that manages receiving data from the serial port. * Mostly changes the global variables that are passed to the * control functions. */ void serialEvent() { char cmd = Serial.read(); Serial.println(); Serial.print("command received is "); Serial.println(cmd); switch (cmd) { // Take off with 't' case 't': Serial.println("Taking Off"); // Yaw: 1-15 // 8 = no turn // 1 = max right turn // 15 = max left turn // // Pitch: 1-15 // 8 = no pitch // 15 = max forward // 1 = max backwards // // Throttle: 0-255 // 0 = off // ~130 = steady flight // ~240 = fast climb // First, go up with lots of throttle for 650ms // yaw: 8 --> no yaw // pitch: 8 --> no pitch // throttle: 240 --> fast climb // delay: 650ms --> enough time to climb, not too long so won't hit ceiling // HoldCommand: a function that sends the same data for a given amount of time // HoldCommand(yaw, pitch, throttle, time-to-hold-in-ms); HoldCommand(8, 8, 240, 650); // set the *global* throttle to steady flight throttle throttleCmd = 130; break; // land with 'x' or 'q' case 'x': case 'q': Land(); break; // throttle commands case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': throttleCmd = atoi(&cmd) * 25; //single character, so we can go from 0 to 255 by inputting 0 to 9 in the serial monitor break; // turn left case 'a': if (yawCmd < 15) { yawCmd ++; } Serial.print("Yaw is "); Serial.println(yawCmd); break; // turn right case 'd': if (yawCmd > 1) { yawCmd --; } Serial.print("Yaw is "); Serial.println(yawCmd); break; // move forwards case 'w': if (pitchCmd < 15){ pitchCmd ++; // moves forward } Serial.print("Pitch is "); Serial.println(pitchCmd); break; // move backwards case 's': if (pitchCmd > 1) { pitchCmd --; // moves backward } Serial.print("Pitch is "); Serial.println(pitchCmd); break; // increase throttle case 'u': if (throttleCmd < 255 - 6) { throttleCmd += 6; } Serial.print("Throttle is "); Serial.println(throttleCmd); break; // decrease throttle case 'j': if (throttleCmd > 6) { throttleCmd -= 6; } Serial.print("Trottle is "); Serial.println(throttleCmd); break; // change channel case 'c': Serial.println("Changing channel"); if (channel >= 2) { channel = 0; } else { channel ++; } Serial.print("Channel is: "); Serial.println(channel); break; // reset yaw and pitch case 'r': Serial.println("resetting yaw and pitch"); yawCmd = 8; pitchCmd = 8; break; default: Serial.println("Unknown command"); } Serial.print("Throttle is at "); Serial.println(throttleCmd); } /* * Loops continuously sending and delaying for the transmission */ void loop() { // Note that serialEvent() gets called on each path of the loop // and runs if there is data at the serial port // we call delay here on the return value of sendPacket because that will // cause us to put the right amount of time between packets. The delay is // not constant, but is instead based on how long the packet was // that we sent delay(sendPacket(yawCmd, pitchCmd, throttleCmd, trimCmd)); }
To use the code, open the Serial Monitor (Tools > Serial Monitor) and use the following commands:
0-9: throttle
w: forward
a: left
s: backwards
d: right
t: take off
u: increase throttle
j: decrease throttle
r: reset pitch and yaw
For more details on this project, please go to:
http://www.abarry.org/likelytobeforgotten/?p=55
What's next?
Now that we can successfully send programmatical commands from Arduino, we can take advantage of the solutions we have learned here in DIY Phone Gadgets to control the IR helicopter using PCs, game consoles, Kinect, tablets, smartphones or whatever electronic gadgets.
Here is a project using Kinect:
Here is a project using brain (your mind) to control a helicopter:
Or a Nunchuk-Wiimote-controlled helicopter, if you need more accuracy:
How to decode IR signal (very useful if you don't have a SYMA S107):
Of course, you can always decode the IR signal from scratch, if your helicopter is not SYMA S107. Here is a great video tutorial:
Here is the project owner's original blog: http://technologyonmymind.blogspot.fr/2012/03/helicopter-auto-pilot-introduction.html
DIY Phone-controlled helicopters with Arduino:
Needless to say, using Arduino as a bridge, we can easily control helicopters. Here is "Yan's helicopter Controller" from DIY Phone Gadgets.
Here is how it works:
1. The Android phone is controlling the Arduino using bluetooth.
2. Arduino is controlling the original helicopter transmitter.
3. The transmitter is programmatically controlling the helicopter.
DIY Phone-controlled helicopters with audio dongle:
There are already some fantastic existing tools in the toy market that are really helpful. Like these audio jack dongles:
These dongles capture the audio signal in the 3.5 audio jack and translate the audio signal into wireless signal.
For normal users, these dongles are just wireless transmitters, compatible with Android or iPhone apps. They can use it to control the helicopter with their smartphones.
For DIYers, the dongles should be capable of transmitting IR or other wireless signals from any smartphone or tablet (Android, iPhone, Blackberry or Windows Phone). You simply produce programmatically some audio sound from the phone. To make a touchscreen controller is so boring because the physical joysticks are way better and more precise. A phone should be a mobile command station to interact with the helicopter with a lot more intelligence. The helicopter should be able to dance with your own written program!
The easiest way to get these dongles is searching "iPhone Android Helicopter" on eBay. Then write your iOS or Android code to produce some audio signal, control your TV, fly your helicopter! Don't forget to share your exciting discoveries with the DIY Phone Gadgets community.
Imagine that you are playing your favorite music while watching a bunch of helicopters dancing in the sky, following the melody and rhythm. Yes, that's so geeky. But you are so happy. What's more beautiful than a creative mind?
Of course, you can always decode the IR signal from scratch, if your helicopter is not SYMA S107. Here is a great video tutorial:
Here is the project owner's original blog: http://technologyonmymind.blogspot.fr/2012/03/helicopter-auto-pilot-introduction.html
DIY Phone-controlled helicopters with Arduino:
Needless to say, using Arduino as a bridge, we can easily control helicopters. Here is "Yan's helicopter Controller" from DIY Phone Gadgets.
Here is how it works:
1. The Android phone is controlling the Arduino using bluetooth.
2. Arduino is controlling the original helicopter transmitter.
3. The transmitter is programmatically controlling the helicopter.
DIY Phone-controlled helicopters with audio dongle:
There are already some fantastic existing tools in the toy market that are really helpful. Like these audio jack dongles:
These dongles capture the audio signal in the 3.5 audio jack and translate the audio signal into wireless signal.
For DIYers, the dongles should be capable of transmitting IR or other wireless signals from any smartphone or tablet (Android, iPhone, Blackberry or Windows Phone). You simply produce programmatically some audio sound from the phone. To make a touchscreen controller is so boring because the physical joysticks are way better and more precise. A phone should be a mobile command station to interact with the helicopter with a lot more intelligence. The helicopter should be able to dance with your own written program!
The easiest way to get these dongles is searching "iPhone Android Helicopter" on eBay. Then write your iOS or Android code to produce some audio signal, control your TV, fly your helicopter! Don't forget to share your exciting discoveries with the DIY Phone Gadgets community.
Imagine that you are playing your favorite music while watching a bunch of helicopters dancing in the sky, following the melody and rhythm. Yes, that's so geeky. But you are so happy. What's more beautiful than a creative mind?
This is great! How could I do this with a Raspberry PI and in Python?
ReplyDeleteUsing the same Arduino code, and use Raspberry Pi and Python to control Arduino:)
Deletehow to use the 1st code that you said is tested. "The first working code (tested)". after you upload that program to your arduino it will automatically run or do you have to press something or whats so ever?? can i ask for the exact schematic diagram without the receiver thing? thank you.
ReplyDeleteAnthony, you don't have too press anything. It will run automatically. The only thing you need to do is to fix the camera and the helicopter's initial positions so that the helicopter will always stay in the sight of the camera.
DeleteSearching the internet has led me to different versions of Arduino. Is there a certain one that works better than others for this coding?
ReplyDeleteNormally we use Arduino Uno, others will definitely work too.
Deletefirst I am surprised to know that IR helicopter can be controlled by the programmatically with android or another mobile application.I is very nice to read this post.
ReplyDeleteSounds easy to me, thanks for the steps though, now I can control my helecopter with my android phone..
ReplyDeleteHi! I have the basic (one mode only) S107 helicopter, but the Arduino code didn't work properly for me. No idea why. Possibly because I tested it in Arduino Mega, although that shouldn't be the reason.
ReplyDeleteIn any case, did some modifications and now it works. Hope it helps someone:
https://gist.github.com/alfongj/5425213
Hey... i want to control syma107 helicopter using kinect sensor n arduino mega. i am working on it for a month but still facing problems. Can you provide me the processing code for controlling it through kinect? Will be extremely thankful to you.
ReplyDeleteI want to know can I use arduino uno R3 instead of the one you used?? Can I change the helicopter?? And can do all this without changing coding ?? And if PC camera coding would work for kinect or not ?? Plz answer all of my questions
ReplyDeleteHi, thanks for sharing your work.
ReplyDeleteI have a problem whith the code.
Processing send a error in line 397.
"the function arrayValue() does not exists"
help me please.
The big rc helicopters reviews will react better to your control contrasted with ones with bring down quality edges.
ReplyDeleteNow, I don't mean to belittle a time honored classic carnival game like the fish pond, but as I stood there watching child after child saunter up, toss their line over and wait for the telling tug that signaled the arrival of a really great sticker, an ugly plastic bug or an enigmatic Chinese finger trap I thought, "Surely there's a better way".Mark Briggs
ReplyDeleteThat was a great message in my carrier, and It's wonderful commands like mind relaxes with understand words of knowledge by information's.
ReplyDeletePython Online certification training
python Training institute in Chennai
Python training institute in Bangalore
Usually I never comment on blogs but your article is so convincing that I never stop myself to say something about it. You’re doing a great job Man, I like it..Heli Banners Australia..Keep it Up!
ReplyDeleteReally very nice blog information for this one and more technical skills are improve,i like that kind of post.
ReplyDeleteapache spark online training
Thanks for your article on social media marketing course in Delhi! You targeted a topic we have already considered a few times. Our result in the past was a "light" version from what you have suggested. But your proposed way is far more structured and therefore we will follow it the next time we touch that topic :) Thanks again!
ReplyDeleteExcellent post for the people who really need information for this technology.
ReplyDeletesql server dba training in bangalore
sql server dba courses in bangalore
sql server dba classes in bangalore
sql server dba training institute in bangalore
sql server dba course syllabus
best sql server dba training
sql server dba course syllabus
best sql server dba training
sql server dba training centers
Really inspirational to hear someone pursuing their dreams and becoming successful instead of following the traditional path. I have read your article about This topic. I think it's good and impressed to know your service. Thanks for share this Information.
ReplyDeleteairplane leasing
This is really nice to read content of this blog. A is very extensive and vast knowledgeable platform has been given by this blog. I really appreciate this blog to has such kind of educational knowledge.
ReplyDeleteHelicopter lessons
I am speechless as to how great this article is. The content is simple to understand and very engaging.
ReplyDeleteSAP training in Mumbai
Best SAP training in Mumbai
SAP training institute Mumbai
This comment has been removed by the author.
ReplyDeleteThis is by far some of the best content I've seen.
ReplyDeleteSAP training in Kolkata
Best SAP training in Kolkata
SAP training institute in Kolkata
The contents in this blogs are very useful,Thanks
ReplyDeletepython training in chennai | python training in annanagar | python training in omr | python training in porur | python training in tambaram | python training in velachery
MP Board 12th Class Blueprint 2021 English Medium & Hindi Medium PDF download, MPBSE 12th Blueprint 2021 Pdf Download, mpbse.nic.in 12th Blue
ReplyDeletePrint, Marking Scheme and Arts, Commerce and Science Streams Chapter wise Weightage pdf download. MP Board 12th Blue Print || MPBSE 12th Model Papers || MPBSE 10th Model Papers
Manabadi AP Intermediate 2nd Year Model Question Paper 2021 MPC, BIPC, CEC, MEC group TM, EM Subject wise Blue Print, Download BIEAP
Intermediate Second Year Model Question Papers, AP Senior Inter Test Papers, Chapter wise important Questions download. || AP Inter MPC, Bi.PC, CEC Blue Print || AP Inter 1st / 2nd Year Model Papers || AP 2nd year inter Test Papers
Kar 1st / 2nd PUC Blue Print || UP Board 12th Blueprint 2021
Wonderful post for the people who really need information for this technology.Great job. It’s amazing...
ReplyDeleteAngular JS Training in Chennai | Certification | Online Training Course | Angular JS Training in Bangalore | Certification | Online Training Course | Angular JS Training in Hyderabad | Certification | Online Training Course | Angular JS Training in Coimbatore | Certification | Online Training Course | Angular JS Training in Online | Certification | Online Training Course
Wonderful post for the people who really need information for this technology.Great job. It’s amazing...
ReplyDeleteAWS training in Chennai
AWS Online Training in Chennai
AWS training in Bangalore
AWS training in Hyderabad
AWS training in Coimbatore
AWS training
Thanks for your marvelous posting! It is very useful and good.
ReplyDeletejava training in chennai
java training in omr
aws training in chennai
aws training in omr
python training in chennai
python training in omr
selenium training in chennai
selenium training in omr
I have read your blog its very attractive and impressive. I like it your blog.
ReplyDeletedata science training in chennai
data science training in tambaram
android training in chennai
android training in tambaram
devops training in chennai
devops training in tambaram
artificial intelligence training in chennai
artificial intelligence training in tambaram
Thanks for your marvelous posting! It is very useful and good.
ReplyDeletehardware and networking training in chennai
hardware and networking training in annanagar
xamarin training in chennai
xamarin training in annanagar
ios training in chennai
ios training in annanagar
iot training in chennai
iot training in annanagar
Fake Bank Statement
ReplyDeleteFake Bank Statement
Fake Bank Statement
Fake Bank Statement
Fake Bank Statement
Fake Bank Statement
Fake Bank Statement
Fake Bank Statement
Fake Bank Statement
ReplyDeleteFake Bank Statement
Fake Bank Statement
Fake Bank Statement
Fake Bank Statement
Fake Bank Statement
Fake Bank Statement
Fake Bank Statement
http://gbasibe.com
ReplyDeletehttp://gbasibe.com
http://gbasibe.com
http://gbasibe.com
http://yaando.com
http://gbasibe.com
http://gbasibe.com
http://gbasibe.com
Wounderful blog thanks for sharing this blog.
ReplyDeleteacte reviews
acte velachery reviews
acte tambaram reviews
acte anna nagar reviews
acte porur reviews
acte omr reviews
acte chennai reviews
acte student reviews
I’m really happy with this informative blog, thank you so much for sharing this. Ogen Infosystem infosystem is a leading Web Designing and SEO Service provider in Delhi, India.
ReplyDeleteWebsite Designing Company in Delhi
Very useful blog. In this blog, I got so much useful information.
ReplyDeletearchitecture of selenium
angularjs future
aws certification validity
android 8.0 oreo
aws interview questions and answers
Thanks for Sharing a Very Informative Post & I read Your Article & I must say that is very helpful post for us.
ReplyDeleteThank you for sharing this useful material. The information you have mentioned here will be useful. I would like to share with you all one useful source of Travel LaTomatina festival in Spain. Explore the world with a Tour to Review where you can find your destination at one place. Here you can get all the information about travel. La Tomatina is an annual festival celebrated in the small town of Bunol, the largest tomato fight in the world. Which may be interesting for you as well.
ReplyDeleteThank you for sharing this useful content. The information you describe here would be useful. I want to share with you all a useful source Telstra Customer Service Number +61-1 800 431 401, which may be interesting for you as well. If you are troubled by problems in your internet or Telecom connectivity and your net surfing then do not worry about it. Telstra Support Number Australia corrects your internet issue.
ReplyDeleteMua vé máy bay tại Aivivu, tham khảo
ReplyDeletevé máy bay đi Mỹ giá rẻ 2021
giá vé máy bay mỹ về việt nam
vé máy bay hà nội đà nẵng vietjet
vé máy bay đi nha trang tháng 7
ve may bay gia re di phu quoc
Each user when purchase printing machine, their primary proverb is to get the quality printouts of any archives. Brother printer error code Ts-02 Along these lines, when we talk about quality-based printing administration, Brother Printer is been ideal as it has novel and progressed highlights that make the print work simple. While few errors may also occur during printing from your Brother Printer. brother Error TS-02 is the one most basic blunder numerous users have gone up against during their print work and raised a voice of help to fix it. This particular error issue seems when the WLAN passage or switch can't be distinguished by the framework while printing. You don't have to sway off; we are here to manage you to manage a particularly risky mistake code in an easy way.
ReplyDeleteVery nice post. I just stumbled upon your weblog and wanted to say that I’ve truly enjoyed surfing around your blog posts. In any case I will be subscribing to your feed and I hope you write again soon!CBD oil
ReplyDeleteAs I do not know how to activate Roku, read the recent blog post on your portal. I could understand how to activate Roku and fix activation errors after reading. You have done a great job. I’m happy to mark the best review rating and share the post with new Roku users
ReplyDeletePlease provide some information regarding the Roku.com/support services offered.
Thank you for sharing useful and don't forget, keep sharing useful info: Aluminium pipe manufacturer
ReplyDeleteGreat blog article. Really looking forward to read more. Will read on… 야한동영상
ReplyDeleteWith thanks! Valuable information! I think this is among the most vital info for me. 일본야동
ReplyDeleteThis article is an appealing wealth of useful informative that is interesting and well-written. I commend your hard work on this and thank you for this information. I know it very well that if anyone visits your blog, then he/she will surely revisit it again. 한국야동닷컴
ReplyDeleteThank you. I authentically greeting your way for writing an article. I safe as a majority loved it to my bookmark website sheet list and will checking rear quite than later. 국산야동
ReplyDeleteI have a read all blogs. Your blog is so interactive and information. Keep update more information
ReplyDeletehttps://shrishuddhinashamuktikendrabhopal.business.site/?m=true
Then call a windshield chip and crack repair technician for repair as soon as you can don't be the one testing your luck with that chipped or cracked windshield. how to get cracked mac apps What's more, the catalogue is being constantly updated with free casual games.
ReplyDelete토토사이트 Satisfying blog I am highly satisfied I have been here
ReplyDelete스포츠토토
ReplyDeleteRemarkable posting! A lot of useful details and idea
I was eager to find this page. I needed to thank you for ones time for this especially awesome read!! I certainly truly preferred all aspects of it and I likewise have you book-set apart to look at new data in your blog.
ReplyDeleteMedicare Insurance
Enjoyed reading the article above , really explains everything in detail,the article is very interesting and effective. Thank you and good luck for the upcoming articles
ReplyDeleteXpertscm construction Company is leading construction Company and ranking at the top most position in the list of construction companies in Bihar. They are involve in many commercial and residential projects.
ReplyDeleteDo you want the best air hostess/cabin crew training institutes then There are many training institutes which train youngsters to be cabin crew in flights.But all depends on you what can you do for your better future. So I will recommend you to join Groundtosky Airhostess Training institutes.They are providing quality of training with placements.Here the training is based on the some special features. which require and help you to clear the all rounds of interview step by step.
ReplyDeleteHaving read this I thought it was extremely enlightening. I like you investing some time and energy to assemble this short article. I once atain wind up investing a ton of energy both perusing and posting comments . But so what, it wass still advantageous.
ReplyDeleteNow online shopping is the way of life, we need the best shopping apps to make our lives easier.
ReplyDeleteI think this is one of the most crucial data for me.And i'm happy perusing your article. In any case, should comment on scarcely any broad things, The site style is awesome, the articles is truly fantastic.
ReplyDeleteGet the best deals on the latest software and bundles, Get thousands of latest software at a significant discount. We’ve everything you need for your business.
ReplyDeleteUPVC Pipes are our finest offering, made with high-quality raw materials and cutting-edge technology, and are suitable for both hot and cold water applications. When compared to traditional plastic piping systems, these pipes can sustain higher temperatures.
ReplyDeleteBest interior designing company in patna Bihar. We are the best interior design service provider in patna, the best interior designing company in patna.
ReplyDeleteVery interesting article. Many articles I come across these days really not provide anything that attracts others, but believe me the way you interact is literally awesome.
ReplyDeleteSalesforce Offshore Support Services
Awesome blog.I find it interesting and is pretty fascinating, By reading your blog i got very useful information.Thanks for sharing this blog.
ReplyDeleteSharePoint Support
Thanks for sharing this Informative content. Well explained. Got to learn new things from your Blog.
ReplyDeleteFinancialForce offshore Support
i'm unequipped for perusing articles online especially every now and again, but Im cheerful I did these days. it is chosen dexterously composed, and your focuses are skillfully communicated. I request you agreeably, engage, dont at any point lower composing.! Pain Tool Sai Crack
ReplyDeleteEpubor Ultimate Crack Download is a solitary of the top of the line use of it's sort. This application will help you to change over your records! Thums Up Epubor Torrent
ReplyDeleteThanks for sharing this post, it was great article. Unlock the power of phonics sounds with Ziyyara Edutech's top-notch online phonics classes. Our dedicated platform offers the best phonics classes online.
ReplyDeletevisit Best phonics classes online
Wow, such an amazing chopper it is! Here you can also see some of the best kids puzzles. Such kinds of games can help you to improve your kid's brain and stress capacity.
ReplyDeleteGreat experience I got good information from your blog. Join online tuition center for class 7 with Ziyyara's 100% qualified tutors who are dedicated to unlocking the full potential of every student.
ReplyDeleteBook A Free Demo Today visit home tuition near me for class 7th