/* Copyright: Puzzlebox Productions LLC This code is released under GPL v2. Nov. 14th, 2012 Controls an IR helicopter (such as the Puzzlebox Orbit) with Arduino. This code is compatible with any ATmega 168/328 based Arduino, such as Uno, Duemilanove and Diecimila. Put Sam Knight's PWM library in your ~/sketchbook/libraries/ path to use this sketch. */ #include int IR = 10; // the pin that the Infrared LED is attached to int ON = 128; int OFF = 0; int32_t frequency = 38400; //frequency (in Hz) //variables start with "_" means global variable char _throttle=0; //32~127, default 0 char _pitch=31; //0~63, default 31 char _yaw=78; //16~127, default 78 char _channel='A'; char _command; //generate ON/OFF control signals, with starting and stopping PWM generator void innerCycle(int onTime, int offTime) { pwmWrite(IR, ON); delayMicroseconds(onTime); pwmWrite(IR, OFF); delayMicroseconds(offTime); } void emitCode(char BIT)//emitCode generate LOWs between HIGHs as same as the parameter. { if (BIT) innerCycle(671,732);// 1 else innerCycle(337,402);// 0 } void sendCode(long code) { char n; //starting code, with special time period. innerCycle(730,392); //(773 414) innerCycle(730,392); for (n=28;n>=0;n--) emitCode((code >> n) & 1); //getting bits out from code } long formCode(char throttle,char yaw,char pitch) { char n; long mainCode=0; int checkSum=0; //throttle for (n=6; n>=0; n--) bitWrite(mainCode,17+n,bitRead(throttle,n)); //getting the first 7 digits to mainCode bitWrite(mainCode,16,1); //meaning unclear, possibly left button. //channel selection first half if (_channel=='C') bitWrite(mainCode,15,1); else bitWrite(mainCode,15,0); //this digit equals 0 in channel A or B for (n=6; n>=0; n--) bitWrite(mainCode,8+n,bitRead(yaw,n));//yaw //channel selection second half if (_channel=='A') bitWrite(mainCode,7,1); else bitWrite(mainCode,7,0); //if channel B or C, this digit equals 0; bitWrite(mainCode,6,0);// meaning unclear, possibly right button. for (n=5; n>=0; n--) bitWrite(mainCode,n,bitRead(pitch,n));//pitch // CheckSum for (n=0; n<=20; n=n+4) checkSum += ((mainCode >> n) & B1111);//sum up every 4 digits in the code checkSum=checkSum & B1111; //get the last 4 bits of the sum checkSum=(16-checkSum) & B1111;//16-sum is the formula of this helicopter mainCode= (mainCode << 5) | (checkSum << 1); //get the last 4 digit of CheckSum bitWrite(mainCode,0,1); //finish code return mainCode; //mainCode is a 29 bit binary number } void setup() { pinMode(13, OUTPUT); digitalWrite(13,LOW); //initialize all timers except for 0, to save time keeping functions InitTimersSafe(); //sets the frequency for the specified pin bool success = SetPinFrequencySafe(IR, frequency); //if the pin frequency was set successfully, turn pin 13 on if(success) { digitalWrite(13, HIGH); } Serial.begin(9600); } void setThrottle() { char inByte=0; int a=0; int b=0; int c=0; int newThrottle=0; while (Serial.available() == 0); inByte = Serial.read() - '0'; a = inByte; while (Serial.available() == 0); inByte = Serial.read() - '0'; b = inByte; while (Serial.available() == 0); inByte = Serial.read() - '0'; c = inByte; newThrottle = (a * 100) + (b * 10) + c; if (newThrottle < 0) newThrottle=0; if (newThrottle > 100) newThrottle=100; _throttle=newThrottle; Serial.print("_throttle="); Serial.println(int(_throttle)); } void loop() {int i; if (Serial.available() > 0) { _command = Serial.read(); switch (_command) { case 'P': _throttle=85; Serial.print("_throttle="); Serial.println(int(_throttle)); break; case 'O': _throttle=0; Serial.print("_throttle="); Serial.println(int(_throttle)); break; case 'U': _throttle+=1; Serial.print("_throttle="); Serial.println(int(_throttle)); break; case 'D': _throttle-=1; Serial.print("_throttle="); Serial.println(int(_throttle)); break; case 'L': _yaw+=15; Serial.print("_yaw="); Serial.println(int(_yaw)); break; case 'R': _yaw-=15; Serial.print("_yaw="); Serial.println(int(_yaw)); break; case 'F': _pitch+=5; Serial.print("_pitch="); Serial.println(int(_pitch)); break; case 'B': _pitch-=5; Serial.print("_pitch="); Serial.println(int(_pitch)); break; case '1': _channel='A'; Serial.println("_channel=A"); break; case '2': _channel='B'; Serial.println("_channel=B"); break; case '3': _channel='C'; Serial.println("_channel=C"); break; case 'x': setThrottle(); break; } } sendCode(formCode(_throttle,_yaw,_pitch)); delay(80); }