1 | /* |
---|
2 | Copyright: Puzzlebox Productions LLC |
---|
3 | This code is released under GPL v2. |
---|
4 | Nov. 14th, 2012 |
---|
5 | |
---|
6 | Controls an IR helicopter (such as the Puzzlebox Orbit) with Arduino. |
---|
7 | This code is compatible with any ATmega 168/328 based Arduino, such |
---|
8 | as Uno, Duemilanove and Diecimila. |
---|
9 | Put Sam Knight's PWM library in your ~/sketchbook/libraries/ path to |
---|
10 | use this sketch. |
---|
11 | */ |
---|
12 | |
---|
13 | |
---|
14 | #include <PWM.h> |
---|
15 | |
---|
16 | int IR = 10; // the pin that the Infrared LED is attached to |
---|
17 | int ON = 128; |
---|
18 | int OFF = 0; |
---|
19 | int32_t frequency = 38400; //frequency (in Hz) |
---|
20 | |
---|
21 | //variables start with "_" means global variable |
---|
22 | char _throttle=0; //32~127, default 0 |
---|
23 | char _pitch=31; //0~63, default 31 |
---|
24 | char _yaw=78; //16~127, default 78 |
---|
25 | char _channel='A'; |
---|
26 | char _command; |
---|
27 | |
---|
28 | //generate ON/OFF control signals, with starting and stopping PWM generator |
---|
29 | void innerCycle(int onTime, int offTime) |
---|
30 | { |
---|
31 | pwmWrite(IR, ON); |
---|
32 | delayMicroseconds(onTime); |
---|
33 | pwmWrite(IR, OFF); |
---|
34 | delayMicroseconds(offTime); |
---|
35 | } |
---|
36 | |
---|
37 | void emitCode(char BIT)//emitCode generate LOWs between HIGHs as same as the parameter. |
---|
38 | { |
---|
39 | if (BIT) innerCycle(671,732);// 1 |
---|
40 | else innerCycle(337,402);// 0 |
---|
41 | } |
---|
42 | |
---|
43 | void sendCode(long code) |
---|
44 | { |
---|
45 | char n; |
---|
46 | //starting code, with special time period. |
---|
47 | innerCycle(730,392); //(773 414) |
---|
48 | innerCycle(730,392); |
---|
49 | |
---|
50 | for (n=28;n>=0;n--) emitCode((code >> n) & 1); //getting bits out from code |
---|
51 | |
---|
52 | } |
---|
53 | |
---|
54 | long formCode(char throttle,char yaw,char pitch) |
---|
55 | { |
---|
56 | char n; |
---|
57 | long mainCode=0; |
---|
58 | int checkSum=0; |
---|
59 | |
---|
60 | //throttle |
---|
61 | for (n=6; n>=0; n--) bitWrite(mainCode,17+n,bitRead(throttle,n)); //getting the first 7 digits to mainCode |
---|
62 | |
---|
63 | bitWrite(mainCode,16,1); //meaning unclear, possibly left button. |
---|
64 | |
---|
65 | //channel selection first half |
---|
66 | if (_channel=='C') bitWrite(mainCode,15,1); |
---|
67 | else bitWrite(mainCode,15,0); //this digit equals 0 in channel A or B |
---|
68 | |
---|
69 | for (n=6; n>=0; n--) bitWrite(mainCode,8+n,bitRead(yaw,n));//yaw |
---|
70 | |
---|
71 | //channel selection second half |
---|
72 | if (_channel=='A') bitWrite(mainCode,7,1); |
---|
73 | else bitWrite(mainCode,7,0); //if channel B or C, this digit equals 0; |
---|
74 | |
---|
75 | bitWrite(mainCode,6,0);// meaning unclear, possibly right button. |
---|
76 | |
---|
77 | for (n=5; n>=0; n--) bitWrite(mainCode,n,bitRead(pitch,n));//pitch |
---|
78 | |
---|
79 | // CheckSum |
---|
80 | for (n=0; n<=20; n=n+4) checkSum += ((mainCode >> n) & B1111);//sum up every 4 digits in the code |
---|
81 | |
---|
82 | checkSum=checkSum & B1111; //get the last 4 bits of the sum |
---|
83 | checkSum=(16-checkSum) & B1111;//16-sum is the formula of this helicopter |
---|
84 | |
---|
85 | mainCode= (mainCode << 5) | (checkSum << 1); //get the last 4 digit of CheckSum |
---|
86 | |
---|
87 | bitWrite(mainCode,0,1); //finish code |
---|
88 | return mainCode; //mainCode is a 29 bit binary number |
---|
89 | } |
---|
90 | |
---|
91 | void setup() |
---|
92 | { |
---|
93 | pinMode(13, OUTPUT); |
---|
94 | digitalWrite(13,LOW); |
---|
95 | //initialize all timers except for 0, to save time keeping functions |
---|
96 | InitTimersSafe(); |
---|
97 | |
---|
98 | //sets the frequency for the specified pin |
---|
99 | bool success = SetPinFrequencySafe(IR, frequency); |
---|
100 | |
---|
101 | //if the pin frequency was set successfully, turn pin 13 on |
---|
102 | if(success) { |
---|
103 | digitalWrite(13, HIGH); |
---|
104 | } |
---|
105 | Serial.begin(9600); |
---|
106 | } |
---|
107 | |
---|
108 | void setThrottle() { |
---|
109 | |
---|
110 | char inByte=0; |
---|
111 | int a=0; |
---|
112 | int b=0; |
---|
113 | int c=0; |
---|
114 | int newThrottle=0; |
---|
115 | |
---|
116 | while (Serial.available() == 0); |
---|
117 | inByte = Serial.read() - '0'; |
---|
118 | a = inByte; |
---|
119 | |
---|
120 | while (Serial.available() == 0); |
---|
121 | inByte = Serial.read() - '0'; |
---|
122 | b = inByte; |
---|
123 | |
---|
124 | while (Serial.available() == 0); |
---|
125 | inByte = Serial.read() - '0'; |
---|
126 | c = inByte; |
---|
127 | |
---|
128 | newThrottle = (a * 100) + (b * 10) + c; |
---|
129 | |
---|
130 | if (newThrottle < 0) |
---|
131 | newThrottle=0; |
---|
132 | |
---|
133 | if (newThrottle > 100) |
---|
134 | newThrottle=100; |
---|
135 | |
---|
136 | _throttle=newThrottle; |
---|
137 | |
---|
138 | Serial.print("_throttle="); |
---|
139 | Serial.println(int(_throttle)); |
---|
140 | |
---|
141 | } |
---|
142 | |
---|
143 | void loop() |
---|
144 | {int i; |
---|
145 | if (Serial.available() > 0) |
---|
146 | { |
---|
147 | _command = Serial.read(); |
---|
148 | switch (_command) |
---|
149 | { |
---|
150 | case 'P': _throttle=85; Serial.print("_throttle="); Serial.println(int(_throttle)); break; |
---|
151 | case 'O': _throttle=0; Serial.print("_throttle="); Serial.println(int(_throttle)); break; |
---|
152 | case 'U': _throttle+=1; Serial.print("_throttle="); Serial.println(int(_throttle)); break; |
---|
153 | case 'D': _throttle-=1; Serial.print("_throttle="); Serial.println(int(_throttle)); break; |
---|
154 | case 'L': _yaw+=15; Serial.print("_yaw="); Serial.println(int(_yaw)); break; |
---|
155 | case 'R': _yaw-=15; Serial.print("_yaw="); Serial.println(int(_yaw)); break; |
---|
156 | case 'F': _pitch+=5; Serial.print("_pitch="); Serial.println(int(_pitch)); break; |
---|
157 | case 'B': _pitch-=5; Serial.print("_pitch="); Serial.println(int(_pitch)); break; |
---|
158 | case '1': _channel='A'; Serial.println("_channel=A"); break; |
---|
159 | case '2': _channel='B'; Serial.println("_channel=B"); break; |
---|
160 | case '3': _channel='C'; Serial.println("_channel=C"); break; |
---|
161 | case 'x': setThrottle(); break; |
---|
162 | } |
---|
163 | } |
---|
164 | |
---|
165 | sendCode(formCode(_throttle,_yaw,_pitch)); |
---|
166 | delay(80); |
---|
167 | |
---|
168 | } |
---|