blob: 888aabc47e8ff5b3cda386616f425e0e5597f9a1 [file] [log] [blame]
Erik Gilling3edead52011-03-08 15:59:23 -08001#include <Wire.h>
2#include <Servo.h>
3
Erik Gilling9c16e962011-03-16 17:27:09 -07004#include <Max3421e.h>
5#include <Usb.h>
6#include <AndroidAccessory.h>
Erik Gilling3edead52011-03-08 15:59:23 -08007
Erik Gillingccfe9392011-04-04 10:21:14 -07008#include <CapSense.h>
9
Erik Gilling3edead52011-03-08 15:59:23 -080010#define LED3_RED 2
Erik Gillingea909002011-03-16 15:07:07 -070011#define LED3_GREEN 4
12#define LED3_BLUE 3
Erik Gilling3edead52011-03-08 15:59:23 -080013
14#define LED2_RED 5
Erik Gillingea909002011-03-16 15:07:07 -070015#define LED2_GREEN 7
16#define LED2_BLUE 6
Erik Gilling3edead52011-03-08 15:59:23 -080017
18#define LED1_RED 8
Erik Gillingea909002011-03-16 15:07:07 -070019#define LED1_GREEN 10
20#define LED1_BLUE 9
Erik Gilling3edead52011-03-08 15:59:23 -080021
22#define SERVO1 11
23#define SERVO2 12
24#define SERVO3 13
25
Erik Gillingccfe9392011-04-04 10:21:14 -070026#define TOUCH_RECV 14
27#define TOUCH_SEND 15
Erik Gilling3edead52011-03-08 15:59:23 -080028
29#define RELAY1 A0
30#define RELAY2 A1
31
32#define LIGHT_SENSOR A2
33#define TEMP_SENSOR A3
34
35#define BUTTON1 A6
36#define BUTTON2 A7
37#define BUTTON3 A8
38
39#define JOY_SWITCH A9 // pulls line down when pressed
40#define JOY_nINT A10 // active low interrupt input
41#define JOY_nRESET A11 // active low reset output
42
Erik Gilling9c16e962011-03-16 17:27:09 -070043AndroidAccessory acc("Google, Inc.",
44 "DemoKit",
45 "DemoKit Arduino Board",
46 "1.0",
47 "http://www.android.com",
48 "0000000012345678");
Erik Gilling3edead52011-03-08 15:59:23 -080049Servo servos[3];
50
Erik Gillingccfe9392011-04-04 10:21:14 -070051CapSense touch_robot = CapSense(TOUCH_SEND, TOUCH_RECV); // 10M ohm resistor on demo shield
52
Erik Gilling3edead52011-03-08 15:59:23 -080053void setup();
54void loop();
55
Erik Gilling3edead52011-03-08 15:59:23 -080056void init_buttons()
57{
58 pinMode( BUTTON1, INPUT );
59 pinMode( BUTTON2, INPUT );
60 pinMode( BUTTON3, INPUT );
Erik Gilling894c5eb2011-04-04 10:46:13 -070061 pinMode( JOY_SWITCH, INPUT );
Erik Gilling3edead52011-03-08 15:59:23 -080062
63 digitalWrite( BUTTON1, HIGH ); // enable the internal pullups
64 digitalWrite( BUTTON2, HIGH );
65 digitalWrite( BUTTON3, HIGH );
Erik Gilling894c5eb2011-04-04 10:46:13 -070066 digitalWrite( JOY_SWITCH, HIGH );
Erik Gilling3edead52011-03-08 15:59:23 -080067}
68
69
70void init_relays()
71{
72 pinMode( RELAY1, OUTPUT );
73 pinMode( RELAY2, OUTPUT );
74}
75
76
77void init_leds()
78{
79 digitalWrite( LED1_RED, 1 );
80 digitalWrite( LED1_GREEN, 1 );
81 digitalWrite( LED1_BLUE, 1 );
82
83 pinMode( LED1_RED, OUTPUT );
84 pinMode( LED1_GREEN, OUTPUT );
85 pinMode( LED1_BLUE, OUTPUT );
86
87 digitalWrite( LED2_RED, 1 );
88 digitalWrite( LED2_GREEN, 1 );
89 digitalWrite( LED2_BLUE, 1 );
90
91 pinMode( LED2_RED, OUTPUT );
92 pinMode( LED2_GREEN, OUTPUT );
93 pinMode( LED2_BLUE, OUTPUT );
94
95 digitalWrite( LED3_RED, 1 );
96 digitalWrite( LED3_GREEN, 1 );
97 digitalWrite( LED3_BLUE, 1 );
98
99 pinMode( LED3_RED, OUTPUT );
100 pinMode( LED3_GREEN, OUTPUT );
101 pinMode( LED3_BLUE, OUTPUT );
102}
103
104void init_joystick( int threshold );
105
Erik Gilling894c5eb2011-04-04 10:46:13 -0700106byte b1, b2, b3, b4, c;
Erik Gilling3edead52011-03-08 15:59:23 -0800107void setup()
108{
109 Serial.begin( 115200 );
110 Serial.print("\r\nStart");
111
112 init_leds();
113 init_relays();
114 init_buttons();
115 init_joystick( 5 ); // initialize with thresholding enabled, dead zone of 5 units
116
Erik Gillingccfe9392011-04-04 10:21:14 -0700117 touch_robot.set_CS_AutocaL_Millis(0xFFFFFFFF); // autocalibrate OFF
Erik Gilling3edead52011-03-08 15:59:23 -0800118
119 servos[0].attach(SERVO1);
120 servos[0].write(90);
121 servos[1].attach(SERVO2);
122 servos[1].write(90);
123 servos[2].attach(SERVO3);
124 servos[2].write(90);
125
Erik Gilling9c16e962011-03-16 17:27:09 -0700126
127 b1 = digitalRead(BUTTON1);
128 b2 = digitalRead(BUTTON2);
129 b3 = digitalRead(BUTTON3);
Erik Gilling894c5eb2011-04-04 10:46:13 -0700130 b4 = digitalRead(JOY_SWITCH);
Erik Gillingccfe9392011-04-04 10:21:14 -0700131 c = 0;
Erik Gilling9c16e962011-03-16 17:27:09 -0700132
133 acc.powerOn();
Erik Gilling3edead52011-03-08 15:59:23 -0800134}
135
Erik Gilling3edead52011-03-08 15:59:23 -0800136void loop()
137{
Erik Gilling3edead52011-03-08 15:59:23 -0800138 byte err;
Erik Gilling9c16e962011-03-16 17:27:09 -0700139 byte idle;
140 static byte count = 0;
141 byte msg[3];
Erik Gillingccfe9392011-04-04 10:21:14 -0700142 long touchcount;
Erik Gilling3edead52011-03-08 15:59:23 -0800143
Erik Gilling9c16e962011-03-16 17:27:09 -0700144 if (acc.isConnected()) {
145 int len = acc.read(msg, sizeof(msg), 1);
146 int i;
147 byte b;
148 uint16_t val;
149 int x, y;
150 char c0;
Erik Gilling3edead52011-03-08 15:59:23 -0800151
Erik Gilling9c16e962011-03-16 17:27:09 -0700152 if (len > 0) {
153 // XXX: assumes only one command per packet
154 Serial.print(msg[0], HEX);
155 Serial.print(":");
156 Serial.print(msg[1], HEX);
157 Serial.print(":");
158 Serial.println(msg[2], HEX);
159 if (msg[0] == 0x2) {
160 if (msg[1] == 0x0)
161 analogWrite( LED1_RED, 255 - msg[2]);
162 else if (msg[1] == 0x1)
163 analogWrite( LED1_GREEN, 255 - msg[2]);
164 else if (msg[1] == 0x2)
165 analogWrite( LED1_BLUE, 255 - msg[2]);
166 else if (msg[1] == 0x3)
167 analogWrite( LED2_RED, 255 - msg[2]);
168 else if (msg[1] == 0x4)
169 analogWrite( LED2_GREEN, 255 - msg[2]);
170 else if (msg[1] == 0x5)
171 analogWrite( LED2_BLUE, 255 - msg[2]);
172 else if (msg[1] == 0x6)
173 analogWrite( LED3_RED, 255 - msg[2]);
174 else if (msg[1] == 0x7)
175 analogWrite( LED3_GREEN, 255 - msg[2]);
176 else if (msg[1] == 0x8)
177 analogWrite( LED3_BLUE, 255 - msg[2]);
178 else if (msg[1] == 0x10)
179 servos[0].write(map(msg[2], 0, 255, 0, 180));
180 else if (msg[1] == 0x11)
181 servos[1].write(map(msg[2], 0, 255, 0, 180));
182 else if (msg[1] == 0x12)
183 servos[2].write(map(msg[2], 0, 255, 0, 180));
184 } else if (msg[0] == 0x3) {
185 if (msg[1] == 0x0)
186 digitalWrite( RELAY1, msg[2] ? HIGH : LOW );
187 else if (msg[1] == 0x1)
188 digitalWrite( RELAY2, msg[2] ? HIGH : LOW );
Erik Gilling3edead52011-03-08 15:59:23 -0800189
Erik Gilling3edead52011-03-08 15:59:23 -0800190 }
Erik Gilling3edead52011-03-08 15:59:23 -0800191
192 }
193
Erik Gilling9c16e962011-03-16 17:27:09 -0700194 msg[0] = 0x1;
Erik Gilling3edead52011-03-08 15:59:23 -0800195
Erik Gilling9c16e962011-03-16 17:27:09 -0700196 b = digitalRead(BUTTON1);
197 if (b != b1) {
198 msg[1] = 0;
199 msg[2] = b ? 0 : 1;
200 acc.write(msg, 3);
201 b1 = b;
202 }
203
204 b = digitalRead(BUTTON2);
205 if (b != b2) {
206 msg[1] = 1;
207 msg[2] = b ? 0 : 1;
208 acc.write(msg, 3);
209 b2 = b;
210 }
211
212 b = digitalRead(BUTTON3);
213 if (b != b3) {
214 msg[1] = 2;
215 msg[2] = b ? 0 : 1;
216 acc.write(msg, 3);
217 b3 = b;
218 }
219
Erik Gilling894c5eb2011-04-04 10:46:13 -0700220 b = digitalRead(JOY_SWITCH);
221 if (b != b4) {
222 msg[1] = 4;
223 msg[2] = b ? 0 : 1;
224 acc.write(msg, 3);
225 b4 = b;
226 }
227
Erik Gilling9c16e962011-03-16 17:27:09 -0700228 switch (count++ % 0x10) {
229
230 case 0:
231 val = analogRead(TEMP_SENSOR);
232 msg[0] = 0x4;
233 msg[1] = val >> 8;
234 msg[2] = val & 0xff;
235 acc.write(msg, 3);
236 break;
237
238 case 0x4:
239 val = analogRead(LIGHT_SENSOR);
240 msg[0] = 0x5;
241 msg[1] = val >> 8;
242 msg[2] = val & 0xff;
243 acc.write(msg, 3);
244 break;
245
246 case 0x8:
247 read_joystick(&x, &y);
248 msg[0] = 0x6;
249 msg[1] = constrain(x, -128, 127);
250 msg[2] = constrain(y, -128, 127);
251 acc.write(msg, 3);
252 break;
253
Erik Gilling9c16e962011-03-16 17:27:09 -0700254 /* captoutched needs to be asynchonous */
255 case 0xc:
Erik Gillingccfe9392011-04-04 10:21:14 -0700256 touchcount = touch_robot.capSense(5);
257
258 c0 = touchcount > 750;
259
Erik Gilling9c16e962011-03-16 17:27:09 -0700260 if (c0 != c) {
261 msg[0] = 0x1;
262 msg[1] = 3;
Erik Gillingccfe9392011-04-04 10:21:14 -0700263 msg[2] = c0;
Erik Gilling9c16e962011-03-16 17:27:09 -0700264 acc.write(msg, 3);
265 c = c0;
266 }
Erik Gillingccfe9392011-04-04 10:21:14 -0700267
Erik Gilling9c16e962011-03-16 17:27:09 -0700268 break;
Erik Gilling9c16e962011-03-16 17:27:09 -0700269 }
Rob Tsukb63ed7a2011-05-05 16:39:13 -0700270 } else {
271 analogWrite(LED1_RED, 255);
272 analogWrite(LED1_GREEN, 255);
273 analogWrite(LED1_BLUE, 255);
274 analogWrite(LED2_RED, 255);
275 analogWrite(LED2_GREEN, 255);
276 analogWrite(LED2_BLUE, 255);
277 analogWrite(LED3_RED, 255);
278 analogWrite(LED3_GREEN, 255);
279 analogWrite(LED3_BLUE, 255);
280 servos[0].write(90);
281 servos[0].write(90);
282 servos[0].write(90);
283 digitalWrite(RELAY1, LOW);
284 digitalWrite(RELAY2, LOW);
285
Erik Gilling3edead52011-03-08 15:59:23 -0800286 }
287
Erik Gilling9c16e962011-03-16 17:27:09 -0700288 delay(10);
Erik Gilling3edead52011-03-08 15:59:23 -0800289}
290
291// ==============================================================================
292// Austria Microsystems i2c Joystick
293
294/*
295 If a threshold is provided, the dead zone will be programmed such that interrupts will not
296 be generated unless the threshold is exceeded.
297
298 Note that if you use that mode, you will have to use passage of time with no new interrupts
299 to detect that the stick has been released and has returned to center.
300
301 If you need to explicitly track return to center, pass 0 as the threshold. "Center" will
302 still bounce around a little
303*/
304
305
306void init_joystick( int threshold )
307{
308 byte status = 0;
309
310 pinMode( JOY_SWITCH, INPUT );
311 digitalWrite( JOY_SWITCH, HIGH ); // enable the internal pullup
312
313 pinMode( JOY_nINT, INPUT );
314 digitalWrite( JOY_nINT, HIGH ); // enable the internal pullup
315
316 pinMode( JOY_nRESET, OUTPUT );
317
318 digitalWrite( JOY_nRESET, 1 );
319 delay(1);
320 digitalWrite( JOY_nRESET, 0 );
321 delay(1);
322 digitalWrite( JOY_nRESET, 1 );
323
324 Wire.begin();
325
326 do {
327 status = read_joy_reg( 0x0f ); // XXX need timeout
328 } while ((status & 0xf0) != 0xf0);
329
330 write_joy_reg( 0x2e, 0x86 ); // invert magnet polarity setting, per datasheet
331
332 calibrate_joystick( threshold ); // calibrate & set up dead zone area
333}
334
335
336int offset_X, offset_Y;
337
338void calibrate_joystick( int dz )
339{
340 char iii;
341 int x_cal = 0;
342 int y_cal = 0;
343
344 write_joy_reg( 0x0f, 0x00 ); // Low Power Mode, 20ms auto wakeup
345 // INTn output enabled
346 // INTn active after each measurement
347 // Normal (non-Reset) mode
348 delay(1);
349
350 read_joy_reg( 0x11 ); // dummy read of Y_reg to reset interrupt
351
352 for( iii = 0; iii != 16; iii++ ) { // read coords 16 times & average
353 while( !joystick_interrupt() ) // poll for interrupt
354 ;
355 x_cal += read_joy_reg( 0x10 ); // X pos
356 y_cal += read_joy_reg( 0x11 ); // Y pos
357 }
358
359 offset_X = -(x_cal>>4); // divide by 16 to get average
360 offset_Y = -(y_cal>>4);
361
362 //sprintf(msgbuf, "offsets = %d, %d\n", offset_X, offset_Y);
363 //Serial.print(msgbuf);
364
365 write_joy_reg( 0x12, dz - offset_X ); // Xp, LEFT threshold for INTn
366 write_joy_reg( 0x13, -dz - offset_X ); // Xn, RIGHT threshold for INTn
367 write_joy_reg( 0x14, dz - offset_Y ); // Yp, UP threshold for INTn
368 write_joy_reg( 0x15, -dz - offset_Y ); // Yn, DOWN threshold for INTn
369
370 if ( dz ) // dead zone threshold detect requested?
371 write_joy_reg( 0x0f, 0x04 ); // Low Power Mode, 20ms auto wakeup
372 // INTn output enabled
373 // INTn active when movement exceeds dead zone
374 // Normal (non-Reset) mode
375}
376
377
378void read_joystick( int *x, int *y )
379{
380 *x = read_joy_reg( 0x10 ) + offset_X;
381 *y = read_joy_reg( 0x11 ) + offset_Y; // reading Y clears the interrupt
382}
383
384char joystick_interrupt()
385{
386 return ( digitalRead( JOY_nINT ) == 0 );
387}
388
389
390#define JOY_I2C_ADDR 0x40
391
392char read_joy_reg( char reg_addr )
393{
394 char c;
395
396 Wire.beginTransmission( JOY_I2C_ADDR );
397 Wire.send( reg_addr );
398 Wire.endTransmission();
399
400 Wire.requestFrom( JOY_I2C_ADDR, 1 );
401
402 while(Wire.available())
403 c = Wire.receive();
404
405 return c;
406}
407
408void write_joy_reg( char reg_addr, char val )
409{
410 Wire.beginTransmission( JOY_I2C_ADDR );
411 Wire.send( reg_addr );
412 Wire.send( val );
413 Wire.endTransmission();
414}