root/trunk/goodrobot/robot/plugins/arduino_ethernet/arduino_ethernet.pde

Revision 224, 22.9 KB (checked in by rsm, 9 months ago)

Wrong pin check resolved for servo

Line 
1/*
2  GoodRobot Arduino Ethernet connectivity
3
4  This sketch provides a standard get/set functionality via
5  GoodRobot server. You can (via the server) set any pin to
6  some value or get any value of a pin. Supported pins:
7
8  digitalInp0 to digitalInp19 (analog pins 0 to 5 are mapped
9                               to 14 to 19, if so desired)
10  digitalOut0 to digitalOut13
11  pwm0 to pwm13 (you should make sure that hardware supports
12                 those pins)
13  analogInp0 to  analogInp5 (for all boards)
14  analogInp0 to  analogInp7 (for mini and nano)
15  servo0 to servo13 (pwm pins 9 and 10 won't work)
16
17  For your custom setup, You need to modify the following:
18
19  Note: All changes to be made, as documented below are moved
20  to config_params.h. In general you may not need to edit THIS
21  file, but only config_params.h
22
23  1. Your IP (ip[]), Gateway (gateway[]) and if you need the mac[]
24  2. The putString[] needs to reflect the "robot" name in the
25     GoodRobot server.
26  3. The secret_key as well
27  4. The server IP (server[]) - You may not need to modify this.
28
29  Optionally, you need
30  5. You can configure only some pins, so that, those pins data will
31  be periodically posted to the server. If you don't, all pins will be
32  available for set/get -- but will only send the data, when requested.
33  That may add some latency, which may be undesirable.
34
35  To pre-configure pins, that will periodically send the values to the
36  server, put in code similar to this, in config() function:
37  (NOTE: All digital pins are to use cfg_pins[], including PWM
38  All analog pins are to use cfg_apins[])
39
40  cfg_pins[3] = 'p';  // Pin 3 is set for PWM mode
41  cfg_pins[4] = 'i';  // Pin 4 is set for digital Input mode
42  cfg_pins[5] = 'o';  // Pin 5 is set for digital Output mode
43  cfg_apins[2] = 'a';  // Pin 2 analog mode
44  cfg_pins[9] = 's';  // Pin 9 is set for Servo mode
45
46  6. Enable ResetonTimeout Feature: If there is no real data from the
47  server for timeout time period, you may want to reset the pins to
48  LOW (digitalOut) or 0 (pwm). To configure this feature,
49  put in code similar to this in config() function:
50
51  reset_pins[3] = 'p' // Pin 3, PWM mode, should be reset to 0
52  reset_pins[4] = 'o' // Pin 4, digitalOut mode, should be reset to LOW
53  reset_pins[5] = 't' // Pin 5, PWM mode/Tank drive, should be reset to 127
54  reset_pins[6] = 's' // Pin 6, Servo mode, should be reset to 0
55
56  Also modify, SERVER_TIMEOUT define to suit your needs.
57
58  7. You can also modify SEND_FREQ define to specify how frequently you
59  should send data to the server, when the incoming data is active. Use
60  SEND_IDLE_FREQ to specify the frequency during Idle time.
61
62  8. Arduino provides a way to turn on the PullupResistors, by setting
63  pinmode to INPUT and then doing digitalWrite with HIGH. See
64  http://arduino.cc/en/Tutorial/DigitalPins for details.
65  If you want to do any such thing, you can do that in the config()
66  function, and always use that pin as digitalInp.
67 
68  9. Now, Arduino can act as multiple components. ie. when it sends data, it
69  can identify itself as one of many component names. However, emulating more
70  than two components can hit performance at high speeds, it is limited to
71  two components. To send data as two components, do the following:
72    a) Set max_loops variable to 2. If you leave it as 1, it will continue
73    its current behavior of sending all data as one component.
74    b) Set your first component name (as usual) in putString[] and secret_key[]
75    c) Set your second component name in putString2[] and secret_key2[]. Even
76       if you don't use it, you need to define it though!
77    d) In the config() function, set those pins that need to be sent as first
78       component as cfg_pins[] for digital and cfg_apins[] for analog -- as you
79       would do normally.
80    e) For the second component, set those pins as cfg2_pins[] for digital/pwm
81       and cfg2_apins[]
82
83  10. Arduino has very limited RAM, and thus was causing severe problems, when
84  you exceed that. The worst problem is that we don't know, that we are overwriting
85  heap and stack. So read these URLs:
86     http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213583720/all
87     http://www.arduino.cc/playground/Code/AvailableMemory
88     http://www.arduino.cc/en/Reference/PROGMEM
89  The last url allows us to place some text strings (that won't change) in Flash
90  memory (rather than in SRAM). Because of that some strings are defined differently
91  to place them in Flash mem. Make sure you don't remove those "PROGMEM" definitions.
92 
93  11. Now the sketch supports Servo motor support. You need to do the following to
94  setup Servo motor.
95    a) In config() function, cfg_pins[pin] to 's'. Also if you wish that the software
96    do resetOnTimeout feature, specify reset_pins[pin] to 's'
97    b) Tag names used to send data is "servoX" where X is the pin number.
98  As per Arduino site, pins 9 and 10 are not available for PWM functions, if Servo
99  support is comiled in. Excerpts:
100  As of Arduino 0017, the Servo library supports up to 12 motors on most Arduino boards and
101  48 on the Arduino Mega. On boards other than the Mega, use of the library disables
102  analogWrite() (PWM) functionality on pins 9 and 10, whether or not there is a Servo on those pins.
103  On the Mega, up to 12 servos can be used without interfering with PWM functionality;
104  use of 12 to 23 motors will disable PWM on pins 11 and 12.
105
106*/
107#include <avr/pgmspace.h>
108#include <string.h>
109#include <Ethernet.h>
110#include <Servo.h>
111
112
113/* Max tags that we will process */
114#define MAX_TAGS   20
115/* Max size for each tag and value*/
116#define MAX_TAG_SIZE   20
117#define MAX_VAL_SIZE   20
118
119#define MAX_PINS 20
120#define MAX_APINS 6   /* Max Analog Pins */
121
122/* All analog pins from 0 to 5/7 are mapped to 14 to 19/21
123   INTERNALLY, for easier management. Externally this is not
124   exposed
125*/
126#define ANALOG_MAP_BASE  14 
127#define SEND_BUF_LEN   200
128char sendbuf[SEND_BUF_LEN];
129
130char crlf[] = "\r\n\r\n";
131char lf[] = "\n";
132char lflf[] = "\n\n";
133char id_[] = "id=";
134char comma[] = ",";
135
136char cstr_cl[] PROGMEM = "Content-Length: ";
137char cstr_tag[] PROGMEM = "tag=";
138char cstr_value[] PROGMEM = "value=";
139char cstr_digout[] PROGMEM = "digitalOut";
140char cstr_diginp[] PROGMEM = "digitalInp";
141char cstr_anainp[] PROGMEM = "analogInp";
142char cstr_pwm[] PROGMEM = "pwm";
143char cstr_none[] PROGMEM = "id=0,tag=none,value=none\n";
144char cstr_noctrl[] PROGMEM = "No control data";
145char cstr_connfailed[] PROGMEM = "Connection failed";
146char cstr_dataend[] PROGMEM = "Data end";
147char cstr_timeout[] PROGMEM = "timeout break";
148char cstr_servo[] PROGMEM = "servo";
149
150char cfg_pins[MAX_PINS];
151char cfg_apins[MAX_APINS];
152char cfg2_pins[MAX_PINS];
153char cfg2_apins[MAX_APINS];
154char reset_pins[MAX_PINS];
155
156int pins[MAX_PINS];
157int got_pins[MAX_PINS];
158
159
160
161/* Storage details of received tags */
162char tags[MAX_TAGS][MAX_TAG_SIZE];
163char vals[MAX_TAGS][MAX_VAL_SIZE];
164int tag_cnt, tag_mode, tag_spos, tag_dpos, tag_epos;
165int val_cnt, val_mode, val_spos, val_dpos, val_epos;
166int wait_mode, wait_spos, data_start, data_end;
167int cur_loop = 0;
168int max_loops = 1;
169
170unsigned long control_lastseen = 0;
171unsigned long last_sent_time = 0;
172int control_ready = 0;
173Servo myservo[14];
174
175#include "config_params.h"
176
177PROGMEM const char *string_table[] = {
178  putString,                  // 0
179  hostString,                 // 1
180  secret_key,                 // 2
181  putString2,                 // 3
182  secret_key2,                // 4
183  cstr_cl,                    // 5
184  cstr_tag,                   // 6
185  cstr_value,                 // 7
186  cstr_digout,                // 8
187  cstr_diginp,                // 9
188  cstr_anainp,                // 10
189  cstr_pwm,                   // 11
190  cstr_none,                  // 12
191  cstr_noctrl,                // 13
192  cstr_connfailed,            // 14
193  cstr_dataend,               // 15
194  cstr_timeout,               // 16
195  cstr_servo                  // 17
196};
197
198// Temp buffer
199char tbuf[50];
200
201Client client(server, 80);
202
203/* Equiv of strcat */
204void catstr(char *buf, char src[])
205{
206  int buf_idx, src_idx, i, j;
207
208  buf_idx = strlen(buf);
209  src_idx = strlen(src);
210  for(i=0; i < src_idx; i++)
211    buf[buf_idx+i] = src[i];
212  buf[buf_idx+src_idx] = 0;
213}
214
215/* Like strcat, but the input is a integer
216   which is concat as Decimal to the string */
217void icatstr(char *buf, int num)
218{
219  int i, idx;
220
221  idx = strlen(buf);
222  if(num < 0) {
223    buf[idx++] = '-';
224    num = 0 - num;
225  }
226  for(i=10000; i > 0; i = i / 10)
227    if(num >= i)
228      break;
229
230  if(i==0)
231    buf[idx++] = 0x30;
232
233  for(; i > 0; i = i / 10) {
234    buf[idx++] = 0x30 + (num/i);
235    num = num % i;
236  }
237  buf[idx] = 0;
238}
239
240void setup()
241{
242  Ethernet.begin(mac, ip, gateway);
243  Serial.begin(9600);
244  for(int i=0; i < MAX_PINS; i++) {
245    pins[i] = 0;
246    got_pins[i] = 0;
247    reset_pins[i] = 0;
248    cfg_pins[i] = 0;
249    if(i < MAX_APINS)
250      cfg_apins[i] = 0;
251  }
252  config();
253  initPins();
254
255  delay(2000);
256}
257
258
259int getValLength(unsigned int x)
260{
261  if(x < 10)
262    return 1;
263  if(x < 100)
264    return 2;
265  if(x < 1000)
266    return 3;
267  return 4;
268}
269
270void resetPins()
271{
272  // Reset only
273  if(!control_ready)
274    return;
275  if(millis() - control_lastseen < SERVER_TIMEOUT)
276    return;
277  for(int i=0; i < MAX_PINS; i++) {
278    if(reset_pins[i] == 'p' || reset_pins[i] == 'o') {
279      digitalWrite(i, LOW); // Both for digitalOut and PWM
280      pins[i] = 0;
281    }
282    if(reset_pins[i] == 't') {
283      analogWrite(i, 127);
284      pins[i] = 127;
285    }
286    if(i < 14 && reset_pins[i] == 's') { // Servo motor
287      myservo[i].write(0);
288      pins[i] = 0;
289    }
290  }
291  control_ready = 0;
292  Serial.println("Resetting pins");
293}
294
295void initPins()
296{
297  for(int i=0; i < MAX_PINS; i++) {
298    if(reset_pins[i] == 'p' || reset_pins[i] == 'o')
299      digitalWrite(i, LOW); // Both for digitalOut and PWM
300    if(reset_pins[i] == 't')
301      analogWrite(i, 127);
302    if(i < 14 && cfg_pins[i] == 's') {
303      myservo[i].attach(i);
304      if(reset_pins[i] == 's') // Servo motor
305        myservo[i].write(0);
306    }
307  }
308}
309
310
311int processData()
312{
313  int pin;
314  char *p;
315
316  for(int i=0; i < MAX_PINS; i++)
317    got_pins[i] = 0;
318
319  for(int cnt=0; cnt < tag_cnt; cnt++) {
320    /* If tag is "none", we are done */
321    if(strcmp(tags[cnt], "none") == 0) {
322      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[13]))); // 13 - cstr_noctrl
323      Serial.println(tbuf);
324      return 0;
325    }
326    /* If tag is "error" */
327    if(strcmp(tags[cnt], "error") == 0) {
328      Serial.print("ERROR: ");
329      Serial.println(vals[cnt]);
330      return 0;
331    }
332
333    if(cnt > val_cnt)
334      break;
335
336    /* If tag is digitalOut */
337    strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[8]))); // 8 - cstr_digout
338    if(strncmp(tags[cnt], tbuf, 10) == 0) {
339      pin = atoi(&(tags[cnt][10]));
340      if(pin >= MAX_PINS || pin < 0)
341        continue;
342
343      control_lastseen = millis();
344      control_ready = 1;
345      /* Store the value */
346      got_pins[pin] = 'o';
347      pins[pin] = atoi(vals[cnt]);
348
349      if(pins[pin] > 0)
350        pins[pin] = 1;
351      else
352        pins[pin] = 0;
353
354      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[8]))); // 8 - cstr_digout
355      Serial.print(tbuf);
356
357      Serial.print(pin, DEC);
358
359      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[7]))); // 7 - cstr_value
360      Serial.print(tbuf);
361
362      Serial.println(pins[pin], DEC);
363
364      pinMode(pin, OUTPUT);
365      if(pins[pin])
366        digitalWrite(pin, HIGH);
367      else
368        digitalWrite(pin, LOW);
369    }
370
371    /* If tag is digitalInp */
372    strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[9]))); // 9 - cstr_diginp
373    if(strncmp(tags[cnt], tbuf, 10) == 0) {
374      pin = atoi(&(tags[cnt][10]));
375      if(pin >= MAX_PINS || pin < 0)
376        continue;
377
378      control_lastseen = millis();
379      control_ready = 1;
380      /* Store the value */
381      got_pins[pin] = 'i';
382      pinMode(pin, INPUT);
383      pins[pin] = digitalRead(pin);
384
385      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[9]))); // 9 - cstr_diginp
386      Serial.print(tbuf);
387
388      Serial.print(pin, DEC);
389
390      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[7]))); // 7 - cstr_value
391      Serial.print(tbuf);
392
393      Serial.println(pins[pin], DEC);
394    }
395
396    /* If tag is analogInp */
397    strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[10]))); // 10 - cstr_anainp
398    if(strncmp(tags[cnt], tbuf, 9) == 0) {
399      pin = atoi(&(tags[cnt][9]));
400      if(pin >= MAX_PINS || pin < 0)
401        continue;
402
403      control_lastseen = millis();
404      control_ready = 1;
405      /* Store the value */
406      got_pins[pin+ANALOG_MAP_BASE] = 'a';
407      pins[pin+ANALOG_MAP_BASE] = analogRead(pin);
408
409      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[10]))); // 10 - cstr_anainp
410      Serial.print(tbuf);
411
412      Serial.print(pin, DEC);
413      Serial.print(' ', BYTE);
414
415      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[7]))); // 7 - cstr_value
416      Serial.print(tbuf);
417
418      Serial.print(pins[pin+ANALOG_MAP_BASE], DEC);
419      Serial.print(' ', BYTE);
420      Serial.print('r', BYTE);
421      Serial.print(' ', BYTE);
422      Serial.println(atoi(vals[cnt]));
423    }
424
425    /* If tag is pwm */
426    strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[11]))); // 11 - cstr_pwm
427    if(strncmp(tags[cnt], tbuf, 3) == 0) {
428      pin = atoi(&(tags[cnt][3]));
429      if(pin >= MAX_PINS || pin < 0)
430        continue;
431
432      control_lastseen = millis();
433      control_ready = 1;
434      /* Store the value */
435      got_pins[pin] = 'p';
436      pins[pin] = atoi(vals[cnt]);
437
438      if(pins[pin] < 0)
439        pins[pin] = 0;
440      if(pins[pin] > 255)
441        pins[pin] = 255;
442
443      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[11]))); // 11 - cstr_pwm
444      Serial.print(tbuf);
445
446      Serial.print(&(tags[cnt][3]));
447
448      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[7]))); // 7 - cstr_value
449      Serial.print(tbuf);
450
451      Serial.println(pins[pin], DEC);
452
453      pinMode(pin, OUTPUT);
454      analogWrite(pin, pins[pin]);
455
456    }
457   
458    strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[17]))); // 17 - cstr_servo
459    if(strncmp(tags[cnt], tbuf, 5) == 0) {
460      pin = atoi(&(tags[cnt][5]));
461      if(pin >= 14 || pin < 0)
462        continue;
463
464      control_lastseen = millis();
465      control_ready = 1;
466      /* Store the value */
467      got_pins[pin] = 's';
468      pins[pin] = atoi(vals[cnt]);
469
470      if(pins[pin] < 0)
471        pins[pin] = 0;
472      if(pins[pin] > 180)
473        pins[pin] = 180;
474
475      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[17]))); // 17 - cstr_servo
476      Serial.print(tbuf);
477
478      Serial.print(&(tags[cnt][5]));
479
480      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[7]))); // 7 - cstr_value
481      Serial.print(tbuf);
482
483      Serial.println(pins[pin], DEC);
484
485      myservo[pin].write(pins[pin]);
486
487    }
488   
489    delay(1);
490
491  }
492}
493
494/*
495Parses the input and looks for start and end pattern, and collects
496the value in between. The parameters are:
497
498  char inp     -- Input byte received now
499  char start[] -- start pattern
500  char end[]   -- end   pattern
501  int maxlen   -- Max bytes to match
502  int *mode    -- Is it matching now start(0)|data(1)|end(2)?
503
504  char results[][] -- Store the results. Two dimensional array
505  int  *rescnt     -- Which result is it being stored now?
506  int  maxresults  -- How many results to store?
507
508  int *spos    -- Variable initially initialized to 0, used
509          internally to track the start pattern
510  int *epos    -- Variable initially initialized to 0, used
511          internally to track the end pattern
512  int *dpos    -- Variable initially initialized to 0, used
513          internally to track the data received
514*/
515
516int parseInput(char inp, char start[], char end[], int maxlen, int *mode,
517         char results[][20], int *rescnt, int maxresults,
518         int *spos, int *epos, int *dpos)
519{
520  if(0 == (unsigned long)spos || 0 == (unsigned long)mode)
521    return 0;
522
523  // Start pattern
524  if(*mode == 0) {
525    if(inp == start[*spos]) { /* Matched */
526      if(((*spos)+1) == strlen(start)) { /* end of start */
527        *spos = 0;
528        *mode = 1;
529      } else  {  /* Next start byte */
530        (*spos)++;
531      }
532    }
533    else { /* Not matched */
534      *spos = 0;
535    }
536    /* Simple hack to make this function as waitInput().
537    If end is not defined, then we consider *rescnt as ready and
538    end this function
539    */
540    if(end == NULL && *mode == 1) {
541      *mode = 0;
542      return 1;
543    }
544    return 0;
545  }
546
547  if(0 == (unsigned long)results || 0 == (unsigned long)rescnt)
548    return 0;
549  if(0 == (unsigned long)dpos || 0 == (unsigned long)epos)
550    return 0;
551
552  if(*rescnt > maxresults)
553    return 0;
554
555  // Data pattern (still store, even before end is matched)
556  if(*mode == 1) {
557    if(*dpos < maxlen) {
558      /* We increment now, but after end pattern resolves,
559         it is subtracted
560       */
561      results[*rescnt][*dpos] = inp;
562      (*dpos)++;
563      results[*rescnt][*dpos] = 0;
564    }
565    else {
566      /* Has exceeded maxlen */
567      results[*rescnt][*dpos] = 0;
568    }
569     
570  }
571
572  if(0 == (unsigned long)end)
573    return 0;
574 
575  // end pattern (continue after storing data pattern)
576  if(*mode > 0) {
577    if(inp == end[*epos]) { /* Matched */
578      if(((*epos)+1) == strlen(end)) { /* end of end */
579        *spos = *epos = *mode = 0;
580        *dpos = *dpos - strlen(end);
581        results[*rescnt][*dpos] = 0;
582        *dpos = 0;
583        (*rescnt)++;
584        return 1;
585      }
586      else { /* next end byte */
587        (*epos)++;
588      }
589    }
590    else { /* Not matched */
591      *epos = 0;
592    }
593    return 0;
594  }
595
596  return 0;
597}
598
599int getContentLength()
600{
601  int len = 0;
602  int pin, stdtxt;
603  int cfg, cfga;
604
605  /* Find content length */
606  stdtxt = 17; // strlen("id=0,tag=,value=\n");
607  for(pin=0; pin < MAX_PINS; pin++) {
608
609    cfg = cfga = 0;
610    if(cur_loop == 0)  {
611      cfg = cfg_pins[pin];
612      if(pin >= ANALOG_MAP_BASE)
613        cfga = cfg_apins[pin];
614    }
615    if(cur_loop == 1) {
616      cfg = cfg2_pins[pin];
617      if(pin >= ANALOG_MAP_BASE)
618        cfga = cfg2_apins[pin];
619    }
620
621    /* Set pre-configured pins here */
622    if(!got_pins[pin]) {
623      if(cfg) {
624        got_pins[pin] = cfg;
625        if(cfg == 'i')
626          pins[pin] = digitalRead(pin);
627      }
628      if(pin >= ANALOG_MAP_BASE && cfga) {
629        got_pins[pin] = 'a';
630        pins[pin] = analogRead(pin-ANALOG_MAP_BASE);
631      }
632    }
633
634    if(!got_pins[pin])
635      continue;
636
637    len += stdtxt + 1;  /* 1 is for pin number */
638    /* If pin number is greater than 9 */
639    if(pin > 9)
640      len++;
641    if(got_pins[pin] == 'o') /* digitalOut and value */
642      len += 10 + 1;
643    if(got_pins[pin] == 'i') /* digitalInp and value */
644      len += 10 + 1;
645    if(got_pins[pin] == 'a') /* analogInp */
646      len += 9 + getValLength(pins[pin]) - 1; /* -1 for pin number mapping */
647    if(got_pins[pin] == 'p') /* pwm */
648      len += 3 + getValLength(pins[pin]);
649    if(got_pins[pin] == 's') /* servo */
650      len += 5 + getValLength(pins[pin]);
651  }
652
653  if(len==0) {
654    len += stdtxt + 8; // 8 is none twice
655  }
656
657  return len;
658}
659
660
661int sendData(int len)
662{
663  int pin = 0;
664  int id = 0;
665
666  client.connect();
667
668  if(!client.connected()) {
669    client.stop();
670    if(!client.connect()) {
671      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[14]))); // 14 - cstr_connfailed
672      Serial.println(tbuf);
673      return false;
674    }
675  }
676
677  /* Send data */ 
678  // Serial.println("Connected!");
679  sendbuf[0] = 0;
680  if(cur_loop == 0)
681    strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[0]))); // 0 - putString
682  if(cur_loop == 1)
683    strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[3]))); // 3 - putString2
684
685  strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[1]))); // 1 - hostString
686
687  if(cur_loop == 0)
688    strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[2]))); // 2 - secret_key
689  if(cur_loop == 1)
690    strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[4]))); // 4 - secret_key2
691
692  strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[5]))); // 5 - cstr_cl
693  icatstr(sendbuf, len);
694  catstr(sendbuf, crlf);
695
696  for(pin=id=0; pin < MAX_PINS; pin++) {
697    if(!got_pins[pin])
698      continue;
699
700    catstr(sendbuf, id_);
701    icatstr(sendbuf, id++);
702
703    catstr(sendbuf, comma);
704    strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[6]))); // 6 - cstr_tag
705
706    if(got_pins[pin] == 'o') /* digitalOut and value */
707      strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[8]))); // 8 - cstr_digout
708    if(got_pins[pin] == 'i') /* digitalInp and value */
709      strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[9]))); // 9 - cstr_diginp
710    if(got_pins[pin] == 'a') /* analogInp */
711      strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[10]))); // 10 - cstr_anainp
712    if(got_pins[pin] == 'p') /* pwm */
713      strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[11]))); // 11 - cstr_pwm
714    if(got_pins[pin] == 's') /* servo */
715      strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[17]))); // 17 - cstr_servo
716     
717    if(got_pins[pin] == 'a')
718      icatstr(sendbuf, pin-ANALOG_MAP_BASE);
719    else
720      icatstr(sendbuf, pin);
721
722    catstr(sendbuf, comma);
723    strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[7]))); // 7 - cstr_value
724    icatstr(sendbuf, pins[pin]);
725    catstr(sendbuf, lf);
726
727    /* Make sure we don't exceed sendbuf */
728    if(strlen(sendbuf) > SEND_BUF_LEN-50) {
729      client.print(sendbuf);
730      sendbuf[0] = 0;
731    }
732  }
733
734  if(id == 0)
735    strcat_P(sendbuf, (char*)pgm_read_word(&(string_table[12]))); // 12 - cstr_none
736
737  catstr(sendbuf, crlf);
738  client.print(sendbuf);
739  last_sent_time = millis();
740}
741
742int getData()
743{
744  unsigned long loop_time = 0;
745
746  data_start = data_end = 0;
747  tag_cnt = tag_mode = tag_spos = tag_dpos = tag_epos = 0;
748  val_cnt = val_mode = val_spos = val_dpos = val_epos = 0;
749  wait_mode = wait_spos = 0;
750  sendbuf[0] = 0;
751
752  /* Wait in a small loop, until data arrives */
753  loop_time = millis();
754  while(1) {
755    if(client.available()) {
756      char inp = client.read();
757      if(data_start == 0 && parseInput(inp, crlf, NULL, 0, &wait_mode,
758                                       NULL, NULL, 0, &wait_spos, NULL, NULL)) {
759        data_start = 1;
760        wait_mode = wait_spos = 0;
761      }
762      if(data_start == 1) {
763        parseInput(inp, ",tag=", ",", MAX_TAG_SIZE - 1, &tag_mode,
764                   tags, &tag_cnt, MAX_TAGS,
765                   &tag_spos, &tag_epos, &tag_dpos);
766        parseInput(inp, ",value=", "\n", MAX_VAL_SIZE - 1, &val_mode,
767                   vals, &val_cnt, MAX_TAGS,
768                   &val_spos, &val_epos, &val_dpos);
769        /* For data_end */
770        data_end = parseInput(inp,lflf, NULL, 0, &wait_mode,
771                   NULL, NULL, 0, &wait_spos, NULL, NULL);
772        if(data_end) {
773          // Serial.println(cstr_dataend);
774          while(client.available()) { client.read(); }
775          break;
776        }
777        continue;
778
779      }
780      continue;
781    }
782   
783    if(millis() - loop_time > 10000) {
784      strcpy_P(tbuf, (char*)pgm_read_word(&(string_table[16]))); // 16 - cstr_timeout
785      Serial.println(tbuf);
786      break;
787    }
788   
789    resetPins();
790    // delay(1);
791  }
792 
793}
794
795
796void loop()
797{
798  int len;
799  unsigned long tm;
800
801  tm = millis();
802  if((control_ready && tm - last_sent_time > SEND_FREQ) ||
803     (!control_ready && tm - last_sent_time > SEND_IDLE_FREQ)) {
804
805    for(cur_loop=0; cur_loop < max_loops; cur_loop++) {
806      len = getContentLength();
807      sendData(len);
808      getData();
809      processData();
810    }
811  }
812
813  resetPins();
814}
815
Note: See TracBrowser for help on using the browser.