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.
ReplyDeleteAs I read the blog I felt a tug on the heartstrings. it exhibits how much effort has been put into this.
DeleteFinal Year Project Domains for CSE
Spring Training in Chennai
Project Centers in Chennai for CSE
Spring Framework Corporate TRaining
Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a Java developer learn from Java Training in Chennai. or learn thru Java Online Training in India . Nowadays Java has tons of job opportunities on various vertical industry.
ReplyDeleteThanks for your marvelous posting! It is very useful and good. Come on. I want to introduce an get app installs, I try it and I feel it is so good to rank app to top in app store search results, have you ever heard it?
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
ReplyDeleteVery nice post here and thanks for it .I always like and such a super contents of these post.Excellent and very cool idea and great content of different kinds of the valuable information's.
ReplyDeleterpa training in bangalore
best rpa training in bangalore
RPA training in bangalore
rpa course in bangalore
rpa training in chennai
rpa online training
That 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
Whoa! I’m enjoying the template/theme of this website. It’s simple, yet effective. A lot of times it’s very hard to get that “perfect balance” between superb usability and visual appeal. I must say you’ve done a very good job with this.
ReplyDeleteAWS Training in Bangalore | Best AWS Amazon Web Services…
Amazon Web Services (AWS) Training in Pune India
AWS Training | AWS Training and Certification | AWS online training
AWS Training in Bangalore cost| Aws training in Bangalore with placements
All are saying the same thing repeatedly, but in your blog I had a chance to get some useful and unique information, I love your writing style very much, I would like to suggest your blog in my dude circle, so keep on updates.
ReplyDeletemicrosoft azure training in bangalore
rpa training in bangalore
best rpa training in bangalore
rpa online training
Your good knowledge and kindness in playing with all the pieces were very useful. I don’t know what I would have done if I had not encountered such a step like this.
ReplyDeleteAWS Training in pune
AWS Online Training
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!
ReplyDeleteLearn the Python Training in Bangalore - Learn python course from ExcelR with real-time training from
ReplyDeleteexpert trainers and placement assistance.
Understand the Python course with live project and assignments, which help you to be successfull in your Python domain.
ExcelR is one of the best insutitute in Bangalore for top noted courses like, Data Science Course, Machine Learning Training, Digital Marketing
class room training and live projects, and they do 100% job assistance.
For more information about Pythone Training in Bangalore, please visit our website:
For More Information about Top courses in Bangalore, click below
https://www.excelr.com/
Python course in Bangalore
https://www.excelr.com/python-training-in-bangalore
For more videos like Python course, Data Science course, Digital Marketing course & top selected courses.
https://www.youtube.com/channel/UCF2_gALht1C1NsAm3fmFLsg
Really 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!
ReplyDeleteNice information, want to know about Selenium Training In Chennai
ReplyDeleteSelenium Training In Chennai
Data Science Training In Chennai
Protractor Training in Chennai
jmeter training in chennai
Rpa Training Chennai
Rpa Course Chennai
Selenium Training institute In Chennai
Python Training In Chennai
ReplyDeleteRpa Training in Chennai
Rpa Course in Chennai
Blue prism training in Chennai
Data Science Training In Chennai
Data Science Course In Chennai
Data Science Course In Chennai
It is very good and useful for students and developer.Learned a lot of new things from your post Good creation,thanks for give a good information at sap crm.
ReplyDeletemysql dba training in bangalore
mysql dba courses in bangalore
mysql dba classes in bangalore
mysql dba training institute in bangalore
mysql dba course syllabus
best mysql dba training
mysql dba training centers
Excellent 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
Thank you much more giving the Great Post. I appreciate a good job and Keep it up.
ReplyDeletePrimavera Course in Chennai
Best Primavera Training in Chennai
Tableau Training in Chennai
Spark Training in Chennai
Pega Training in Chennai
Appium Training in Chennai
Linux Training in Chennai
Oracle Training in Chennai
Social Media Marketing Courses in Chennai
Primavera Training in Tambaram
Primavera Training in Velachery
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
I do agree your blog for quiz programming concepts, which is very helpful to grow up your knowledge. keep sharing more
ReplyDeleteAWS training in chennai | AWS training in annanagar | AWS training in omr | AWS training in porur | AWS training in tambaram | AWS training in velachery
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 informative article,Your post helped me to understand the future and career prospects & Keep on updating your blog with such awesome article.
ReplyDeleteangular js training in chennai
angular js training in porur
full stack training in chennai
full stack training in porur
php training in chennai
php training in porur
photoshop training in chennai
photoshop training in porur
Contact Cash App Customer Service
ReplyDeleteCash App Customer Service
Cash App Customer Service Number
Cash App Customer Service Phone Number
Cash App Contact Number
https://cashapphelp.support/
https://cashapphelp.support/
==
Cash App Support
Cash App Support Number
Cash App Support Phone Number
Cash App Phone Number
Cash App Toll-Free Number
Cash App Customer Service Phone Number
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://gbasibe.com
http://gbasibe.com
http://gbasibe.com
http://gbasibe.com
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
Good Post! , it was so good to read and useful to improve my knowledge as an updated one, keep blogging.After seeing your article I want to say that also a well-written article with some very good information which is very useful for the readers....thanks for sharing it and do share more posts likethis. https://www.3ritechnologies.com/course/angular-js-training-institute-in-pune/
ReplyDeleteGreat article with fantastic information found useful and unique content enjoyed reading it thank you, looking forward for next blog.
ReplyDeletetypeerror nonetype object is not subscriptable
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
Great Information shared related to massage, Visit here or Click here for more information.
ReplyDeletecurrent version of php
digital marketing tricks
big data examples in real life
community cloud salesforce
android developer interview questions
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.
ReplyDeleteI really happy found this website eventually. Really informative and inoperative, Thanks for the post and effort! Please keep sharing more such blog.
ReplyDeleteData Science
Selenium
ETL Testing
AWS
Python Online Classes
Get huge discount on Home and Kitchen Appliances,Split and Window Air Conditioner, Mobiles & Laptops online , Television, Speakers & more electronics at best price.
ReplyDeleteHITACHI Inverter Split AC
Thank 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
I really appreciate the information that you have shared on your Blog. Thanks for shearing this blog.
ReplyDeleteprinter repair denver
printer repair boise
printer repair chicago
how do i unpause my printer
printer repair albuquerque
printer repair tulsa
hp error code 0x61011bed
nice Post thanks for the information, good information & very helpful for others.
ReplyDeleteMulesoft Training
Looker Training
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
ReplyDeleteIt’s easy to activate Roku using Roku link Code. If you are ready to begin the activation, connect your device to the TV using HDMI port. Then switch the device ON. Create Roku account, sign in and proceed with the activation settings .Collect the code for activation. The process of Roku activation will complete, if you provide the code by visiting the page, Roku.com/link. Please reach out to our network support for assistance.
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
ReplyDeleteReally impressive post. I read it whole and going to share it with my social circules. I enjoyed your article and planning to rewrite it on my own blog SSC Free Online Mock Test
ReplyDeleteKeep up the excellent work, I read few posts on this web site and I think that your weblog is really interesting and has lots of fantastic information . Free SSC CPO Mock Test Online
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. 국산야동
ReplyDeleteTremendous blog quite easy to grasp the subject since the content is very simple to understand. Obviously, this helps the participants to engage themselves in to the subject without much difficulty. Hope you further educate the readers in the same manner and keep sharing the content as always you do.
ReplyDelete인터넷경마
magosucowep
Excellent post with the title, How to activate Roku using the portal Roku.com/link I’m Impressed after reading and I have no other words to comment
ReplyDeleteI could learn Roku.com/link activation procedure quickly after reading your post. Kindly post similar blogs explaining the guidelines to add and activate the entertaining channels on Roku
Let me mark the 100-star rating for your blog post
Keep up the good work
Awaiting more informative blogs from now on
Hello, I'm happy to see some great articles on your site. Would you like to come to my site later? My site also has posts, comments and communities similar to yours. Please visit and take a look 토토사이트
ReplyDeleteThe assignment submission period was over and I was nervous, 우리카지노 and I am very happy to see your post just in time and it was a great help. Thank you ! Leave your blog address below. Please visit me anytime.
ReplyDeleteI finally found what I was looking for! I'm so happy. 안전한놀이터 Your article is what I've been looking for for a long time. I'm happy to find you like this. Could you visit my website if you have time? I'm sure you'll find a post of interest that you'll find interesting.
ReplyDeleteWhile looking for articles on these topics, I came across this article on the site here. As I read your article, I felt like an expert in this field. I have several articles on these topics posted on my site. Could you please visit my homepage? 토토사이트모음
ReplyDeleteWhat a post I've been looking for! I'm very happy to finally read this post. 안전놀이터 Thank you very much. Can I refer to your post on my website? Your post touched me a lot and helped me a lot. If you have any questions, please visit my site and read what kind of posts I am posting. I am sure it will be interesting.
ReplyDeleteHello, I am one of the most impressed people in your article. 안전놀이터추천 I'm very curious about how you write such a good article. Are you an expert on this subject? I think so. Thank you again for allowing me to read these posts, and have a nice day today. Thank you.
ReplyDeleteI have a read all blogs. Your blog is so interactive and information. Keep update more information
ReplyDeletehttps://shrishuddhinashamuktikendrabhopal.business.site/?m=true
Your ideas inspired me very much. 메이저토토사이트모음 It's amazing. I want to learn your writing skills. In fact, I also have a website. If you are okay, please visit once and leave your opinion. Thank you.
ReplyDeleteThen 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토토 I would love to visit this website every day. As this promotes eternal knowledge.
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
ReplyDelete슬롯커뮤니티
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.
ReplyDeleteCasinoMecca
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.
ReplyDeleteRoyalcasino435
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
This article is very attractive. Those who need this information, it's very informative and understandable for those all. Thanks for this information.
ReplyDeleteMicrosoft Dynamics CRM Support
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
ReplyDelete속초콜걸
ReplyDelete청도콜걸
용인콜걸
속초콜걸
동해콜걸
고령콜걸
파주콜걸
파주콜걸
सट्टा मटका (Satta Matka) एक तरह का जुआ होता है आप इसे जुओं का राजा भी कह सकते हैं.
ReplyDelete