source: firmware/ShutterController/ShutterController.ino@ 14730

Last change on this file since 14730 was 14359, checked in by boccone, 12 years ago
new shutter page
File size: 49.8 KB
Line 
1/*
2 * Web Server - for the FACT lid slow control
3 * Need an Ethernet Shield over Arduino.
4 *
5 * based on the work of
6 * Martyn Woerner
7 * Alessandro Calzavara, alessandro(dot)calzavara(at)gmail(dot)com
8 * and Alberto Capponi, bebbo(at)fast-labs net
9 * for Arduino community! :-)
10 *
11 *
12 */
13#include <SPI.h>
14#include <Ethernet.h>
15#include <avr/pgmspace.h>
16
17#include "ShutterController.h"
18
19#define USE_DHCP_FOR_IP_ADDRESS
20#define ENABLE_ETHERNET
21#define SAMPLES 100
22
23// Define MAC and IP addresses
24byte _mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x5C, 0x91 };
25
26#if !defined USE_DHCP_FOR_IP_ADDRESS
27// ip represents the fixed IP address to use if DHCP is disabled.
28IPAddress _ip(10,0,100,36);
29#endif
30//
31
32// Each value is the real current value in the motors;
33// Define Current Limits in [A] - Offset is 0.5A for no load on the motors
34// pushing coefficient ~100 Kg/A
35const double _ZeroCurrent PROGMEM = 0.25; // [A]
36const double _CurrentPushingLimit PROGMEM = 0.70; // 0.7-0.5 = 0.2 -> 20 +/- 5 kg
37const double _OverCurrent PROGMEM = 1.50; // 1.5-0.5 = 1 -> 100 +/- 5 kg
38
39const int _StartPoint = 0;
40const int _StartPointLimit = 70;
41const int _EndPoint = 1024;
42const int _EndPointLimit = 740;
43
44// Define Lid Status levels and labels
45const int _UNKNOWN = 0;
46const int _CLOSED = 1;
47const int _OPEN = 2;
48const int _STEADY = 3;
49const int _MOVING = 4;
50const int _CLOSING = 5;
51const int _OPENING = 6;
52const int _JAMMED = 7;
53const int _MOTOR_FAULT = 8;
54const int _POWER_PROBLEM = 9;
55const int _OVER_CURRENT = 10;
56
57const char* _StatusLabel[] = {"Unknown",
58 "Closed",
59 "Open",
60 "Steady",
61 "Moving",
62 "Closing",
63 "Opening",
64 "Jammed",
65 "Motor Fault",
66 "Power Problem",
67 "Overcurrent"};
68// Define Arduino pins
69const int _pinPWM[2] = {5, 6};
70const int _pinDA[2] = {2, 7};
71const int _pinDB[2] = {3, 8};
72//unsigned char _ENDIAG[2] = {A4, A5};
73
74
75// Define conversion coefficients
76double _ADC2V = 5. / 1024. ; // ADC channel to Volt
77double _V2A = 0.140; // 140 mV/A conversion factor for the
78
79
80// Define sensor value and lid status variables
81double _sensorValue[2] = {0,0};
82double _currentValue[2] = {0,0};
83uint8_t _LidStatus[2] = {0,0};
84
85extern int __bss_end;
86extern void *__brkval;
87
88// Http header token delimiters
89char *pSpDelimiters = " \r\n";
90char *pStxDelimiter = "\002"; // STX - ASCII start of text character
91
92/**********************************************************************************************************************
93* Strings stored in flash of the HTML we will be transmitting
94***********************************************************************************************************************/
95
96// HTTP Request message
97prog_char content_404[] PROGMEM = "HTTP/1.1 404 Not Found\nServer: arduino\nContent-Type: text/html\n\n<html>"
98 "<head><title>Arduino Web Server - Error 404</title></head>"
99 "<body><h1>Error 404: Sorry, that page cannot be found!</h1></body>";
100PROGMEM const char *page_404[] = { content_404 }; // table with 404 page
101
102// HTML Header for pages
103const prog_char content_main_header[] PROGMEM= "HTTP/1.0 200 OK\nServer: arduino\nCache-Control: no-store, no-cache, must-revalidate\n"
104 "Pragma: no-cache\nConnection: close\nContent-Type: text/html\n";
105
106const prog_char content_main_top[] PROGMEM = "<html><head><meta http-equiv=\"refresh\" content=\"5\"/><title>Arduino Web Server</title>"
107 "<style type=\"text/css\">table{border-collapse:collapse;}td{padding:0.25em 0.5em;border:0.5em solid #C8C8C8;}</style>"
108 "</head><body><h1>Arduino Web Server</h1>";
109
110
111const prog_char content_main_menu[] PROGMEM = "<table width=\"500\"><tr><td align=\"center\"><a href=\"/\">Page 1</a></td></tr></table>";
112const prog_char content_main_footer[] PROGMEM = "</body></html>";
113PGM_P contents_main[] PROGMEM = { content_main_header, content_main_top, content_main_menu, content_main_footer }; // table with 404 page
114
115#define CONT_HEADER 0
116#define CONT_TOP 1
117#define CONT_MENU 2
118#define CONT_FOOTER 3
119
120
121// Page 1
122const PROGMEM prog_char http_uri1[] = "/";
123const PROGMEM prog_char content_title1[] = "<h2>Shutter Lid Control - Beta</h2>";
124#ifdef DEBUG
125// To Be Fixed
126const PROGMEM prog_char content_page1[] = "<hr /><form action=\"/__output__\" method=\"POST\">"
127 "<button name=\"Button1\" value=\"valueButton1\" type=\"submit\">Move Motor 1 OUT </button><p>"
128 "<button name=\"Button2\" value=\"valueButton2\" type=\"submit\">Move Motor 1 IN </button><p>"
129 "<button name=\"Button3\" value=\"valueButton3\" type=\"submit\">Move Motor 2 OUT </button><p>"
130 "<button name=\"Button4\" value=\"valueButton4\" type=\"submit\">Move Motor 2 IN </button><p>"
131 "<button name=\"Button5\" value=\"valueButton5\" type=\"submit\">Open Lid</button><p>"
132 "<button name=\"Button6\" value=\"valueButton6\" type=\"submit\">Close Lid</button><p>"
133 "Motor Current 1 = \002 A <p> Motor Current 2 = \002 A <p> Hall Sensor 1 = \002 ADC counts <p> Hall Sensor 2 = \002 ADC counts<p>"
134 "</form></p>";
135#else
136const PROGMEM prog_char content_page1[] = "<hr/><form action=\"/__output__\" method=\"POST\">"
137 "<button name=\"Button5\" value=\"valueButton5\" type=\"submit\">Open Lid</button><p/>"
138 "<button name=\"Button6\" value=\"valueButton6\" type=\"submit\">Close Lid</button><p/>"
139 "<span id=\"cur1\" value=\"\002\"> Motor Current 1 = \002 A </span><p/><span id=\"cur2\" value=\"\002\"> Motor Current 2 = \002 A </span><p/>"
140 "<span id=\"pos1\" value=\"\002\"> Hall Sensor 1 = \002 ADC ounts </span><p/><span id=\"pos2\" valus=\"\002\"> Hall Sensor 2 = \002 ADC counts</span><p/>"
141 "</form></p>";
142 //<br/></body></html>
143#endif
144
145// Page 5
146
147const PROGMEM prog_char http_uri5[] = "/__output__";
148const PROGMEM prog_char content_title5[] = "<h2>Shutter Lid Control - Beta</h2>";
149#ifdef DEBUG
150// To Be Fixed
151const PROGMEM prog_char content_page5[] = "<hr /><form action=\"/__output__\" method=\"POST\">"
152 "<button name=\"Button1\" value=\"valueButton1\" type=\"submit\">Move Motor 1 OUT </button><p>"
153 "<button name=\"Button2\" value=\"valueButton2\" type=\"submit\">Move Motor 1 IN </button><p>"
154 "<button name=\"Button3\" value=\"valueButton3\" type=\"submit\">Move Motor 2 OUT </button><p>"
155 "<button name=\"Button4\" value=\"valueButton4\" type=\"submit\">Move Motor 2 IN </button><p>"
156 "<button name=\"Button5\" value=\"valueButton5\" type=\"submit\">Open Lid</button><p>"
157 "<button name=\"Button6\" value=\"valueButton6\" type=\"submit\">Close Lid</button><p>"
158 "Motor Current 1 = \"\002\" A <p> Motor Current 2 = \"\002\" A <p> Hall Sensor 1 = \"\002\" ADC ounts <p> Hall Sensor 2 = \"\002\" ADC counts<p>"
159 "Lid 1 Status : \"\002\"<p>"
160 "Lid 2 Status : \"\002\"<p><p>"
161 "received a POST request</p></form></p>";
162#else
163const PROGMEM prog_char content_page5[] = "<hr/><form action=\"/__output__\" method=\"POST\">"
164 "<button name=\"Button5\" value=\"valueButton5\" type=\"submit\">Open Lid</button><p/>"
165 "<button name=\"Button6\" value=\"valueButton6\" type=\"submit\">Close Lid</button><p/>"
166 "<span id=\"cur1\" value=\"\002\"> Motor Current 1 = \002 A </span><p/><span id=\"cur2\" value=\"\002\"> Motor Current 2 = \002 A </span><p/>"
167 "<span id=\"pos1\" value=\"\002\"> Hall Sensor 1 = \002 ADC ounts </span><p/><span id=\"pos2\" value=\"\002\"> Hall Sensor 2 = \002 ADC counts</span><p/>"
168 "<span id=\"lid1\" value=\"\002\"> Lid 1 Status : \002</span><p/>"
169 "<span id=\"lid2\" value=\"\002\"> Lid 2 Status : \002</span><p/>"
170 "<p/>received a POST request</form><p/>";
171// <br/></body></html>
172#endif
173
174// declare tables for the pages
175PGM_P contents_titles[] PROGMEM = { content_title1, content_title5 }; // titles
176PGM_P contents_pages [] PROGMEM = { content_page1, content_page5 }; // real content
177
178#ifdef USE_IMAGES
179
180/**********************************************************************************************************************
181* Image strings and data stored in flash for the image UISs we will be transmitting
182***********************************************************************************************************************/
183
184// A Favicon is a little custom icon that appears next to a website's URL in the address bar of a web browser.
185// They also show up in your bookmarked sites, on the tabs in tabbed browsers, and as the icon for Internet shortcuts
186// on your desktop or other folders in Windows.
187const PROGMEM prog_char http_uri6[] = "/favicon.ico"; // favicon Request message
188
189const PROGMEM prog_char content_image_header[] = "HTTP/1.1 200 OK\nServer: arduino\nContent-Length: \002\nContent-Type: image/\002\n\r\n";
190
191#ifdef USE_ARDUINO_ICON
192
193const PROGMEM prog_char content_favicon_data[] = {
194 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x28, 0x01, 0x00, 0x00, 0x16, 0x00,
195 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0xC0, 0xC0, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x41, 0x00, 0x00, 0x14, 0x44, 0x44, 0x44, 0x41, 0x00, 0x00, 0x00, 0x00,
201 0x14, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x23,
202 0x33, 0x20, 0x02, 0x33, 0x32, 0x04, 0x12, 0x30, 0x00, 0x32, 0x23, 0x00, 0x03, 0x21, 0x03, 0x00, 0x00, 0x03, 0x30, 0x03,
203 0x00, 0x30, 0x03, 0x03, 0x33, 0x03, 0x30, 0x33, 0x30, 0x30, 0x03, 0x00, 0x00, 0x03, 0x30, 0x03, 0x00, 0x30, 0x02, 0x30,
204 0x00, 0x32, 0x23, 0x00, 0x03, 0x20, 0x10, 0x23, 0x33, 0x20, 0x02, 0x33, 0x32, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x04, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x41,
206 0x00, 0x00, 0x00, 0x00, 0x14, 0x44, 0x44, 0x44, 0x41, 0x00, 0x00, 0x14, 0x44, 0x44, 0xF8, 0x1F, 0x00, 0x00, 0xE0, 0x07,
207 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01,
209 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00
210 };
211#else
212
213const PROGMEM prog_char content_favicon_data[] = {
214 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x28, 0x01, 0x00, 0x00, 0x16, 0x00,
215 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x33, 0x66, 0x00, 0x33, 0x33, 0x66, 0x00, 0x66, 0x66, 0x99, 0x00, 0x99, 0x99,
218 0x99, 0x00, 0x99, 0x99, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x62, 0x00,
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x26, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x50, 0x00,
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x07, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x76, 0x00,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x77, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
226 0x00, 0x37, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
230 };
231#endif // USE_ARDUINO_ICON
232
233// declare tables for the images
234PGM_P image_header PROGMEM = content_image_header;
235PGM_P data_for_images [] PROGMEM = { content_favicon_data}; // real data
236const int size_for_images [] PROGMEM = { sizeof(content_favicon_data)};
237// declare table for all URIs
238PGM_P http_uris[] PROGMEM = { http_uri1, http_uri5, http_uri6 }; // URIs
239
240
241#else
242PGM_P image_header PROGMEM = NULL;
243PGM_P data_for_images [] PROGMEM = { }; // real data
244const int size_for_images [] PROGMEM = { };
245// declare table for all URIs
246PGM_P http_uris[] PROGMEM = { http_uri1, http_uri5 }; // URIs
247
248#endif // USE_IMAGES
249
250#define NUM_PAGES sizeof(contents_pages) / sizeof(PGM_P)
251#define NUM_IMAGES sizeof(data_for_images) / sizeof(PGM_P) // favicon or png format
252#define NUM_URIS NUM_PAGES + NUM_IMAGES // Pages URIs + favicon URI, etc
253
254/**********************************************************************************************************************
255* Shared variable and Setup()
256***********************************************************************************************************************/
257EthernetServer server(80);
258
259void setup()
260{
261 Serial.begin(115200); // DEBUG
262
263#ifdef ENABLE_ETHERNET
264#ifdef USE_DHCP_FOR_IP_ADDRESS
265 Serial.println("Attempting to obtain a DHCP lease...");
266
267 Ethernet.begin(_mac); // Use DHCP to get an IP address
268#else
269 Serial.println("Using hard-coded ip...");
270 Ethernet.begin(_mac, _ip);
271#endif
272
273
274 Serial.println("A DHCP lease has been obtained.");
275
276 Serial.print("My IP address is ");
277 Serial.println(Ethernet.localIP());
278
279 // Serial.print("Gateway IP address is ");
280 // Serial.println(ip_to_str(gatewayAddr));
281
282 // Serial.print("DNS IP address is ");
283 // Serial.println(ip_to_str(dnsAddr));
284
285
286 server.begin();
287#endif
288 //_Motor.init();
289
290 //For Arduino Motor Shield set pin 4,5,6,7 to output mode
291 pinMode(2, OUTPUT);
292 pinMode(4, OUTPUT);
293 pinMode(5, OUTPUT);
294 pinMode(6, OUTPUT);
295 pinMode(7, OUTPUT);
296 pinMode(8, OUTPUT);
297
298 pinMode(A0, INPUT); //
299 pinMode(A1, INPUT); //
300 pinMode(A2, INPUT); //
301 pinMode(A3, INPUT); //
302
303 // First clear all three prescaler bits:
304 int prescalerVal = 0x07; // create a variable called prescalerVal and set it equal to the binary number "00000111"
305
306 TCCR0B &= ~prescalerVal; // AND the value in TCCR0B with binary number "11111000"
307
308 //Now set the appropriate prescaler bits:
309 prescalerVal = 3; // set prescalerVal equal to binary number "00000001"
310 TCCR0B |= prescalerVal; // OR the value in TCCR0B with binary number "00000001"
311
312 // TCCR0A = _BV(COM0A0) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
313 // TCCR0B = _BV(WGM02) | _BV(CS02);
314 // OCR0A = 180;
315 // OCR0B = 50;
316
317 //pinMode(ledPin, OUTPUT);
318 //setLed(true);
319}
320
321/**********************************************************************************************************************
322* Main loop
323***********************************************************************************************************************/
324
325void loop()
326{
327#ifdef ENABLE_ETHERNET
328 EthernetClient client = server.available();
329#endif
330
331
332#ifdef ENABLE_ETHERNET
333 if (client)
334 {
335 // now client is connected to arduino we need to extract the
336 // following fields from the HTTP request.
337 int nUriIndex; // Gives the index into table of recognized URIs or -1 for not found.
338 BUFFER requestContent; // Request content as a null-terminated string.
339 MethodType eMethod = readHttpRequest(client, nUriIndex, requestContent);
340
341#ifdef DEBUG
342 Serial.print(" o- Read Request type: ");
343 Serial.print(eMethod);
344 Serial.print(" Uri index: ");
345 Serial.print(nUriIndex);
346 Serial.print(" content: ");
347 Serial.print(requestContent);
348 Serial.print("\n");
349#endif
350 if (nUriIndex < 0)
351 {
352 // URI not found
353 sendProgMemAsString(client, (char*)pgm_read_word(&(page_404[0])));
354 }
355 else if (nUriIndex < NUM_PAGES)
356 {
357 // Normal page request, may depend on content of the request
358#ifdef DEBUG
359 Serial.println(" o- Sending page");
360#endif
361 sendPage(client, nUriIndex, requestContent);
362 }
363 else
364 {
365 // Image request
366 sendImage(client, nUriIndex, requestContent);
367 }
368
369 // give the web browser time to receive the data
370 // delay(1);
371 delay(100);
372
373 client.stop();
374 }
375#endif
376
377
378}
379
380#ifdef ENABLE_ETHERNET
381/**********************************************************************************************************************
382* Method for read HTTP Header Request from web client
383*
384* The HTTP request format is defined at http://www.w3.org/Protocols/HTTP/1.0/spec.html#Message-Types
385* and shows the following structure:
386* Full-Request and Full-Response use the generic message format of RFC 822 [7] for transferring entities. Both messages may include optional header fields
387* (also known as "headers") and an entity body. The entity body is separated from the headers by a null line (i.e., a line with nothing preceding the CRLF).
388* Full-Request = Request-Line
389* *( General-Header
390* | Request-Header
391* | Entity-Header )
392* CRLF
393* [ Entity-Body ]
394*
395* The Request-Line begins with a method token, followed by the Request-URI and the protocol version, and ending with CRLF. The elements are separated by SP characters.
396* No CR or LF are allowed except in the final CRLF sequence.
397* Request-Line = Method SP Request-URI SP HTTP-Version CRLF
398* HTTP header fields, which include General-Header, Request-Header, Response-Header, and Entity-Header fields, follow the same generic format.
399* Each header field consists of a name followed immediately by a colon (":"), a single space (SP) character, and the field value.
400* Field names are case-insensitive. Header fields can be extended over multiple lines by preceding each extra line with at least one SP or HT, though this is not recommended.
401* HTTP-header = field-name ":" [ field-value ] CRLF
402***********************************************************************************************************************/
403// Read HTTP request, setting Uri Index, the requestContent and returning the method type.
404MethodType readHttpRequest(EthernetClient & client, int & nUriIndex, BUFFER & requestContent)
405{
406
407
408 BUFFER readBuffer; // Just a work buffer into which we can read records
409 int nContentLength = 0;
410 bool bIsUrlEncoded;
411
412 requestContent[0] = 0; // Initialize as an empty string
413 // Read the first line: Request-Line setting Uri Index and returning the method type.
414 MethodType eMethod = readRequestLine(client, readBuffer, nUriIndex, requestContent);
415 // Read any following, non-empty headers setting content length.
416 readRequestHeaders(client, readBuffer, nContentLength, bIsUrlEncoded);
417
418 if (nContentLength > 0)
419 {
420 // If there is some content then read it and do an elementary decode.
421 readEntityBody(client, nContentLength, requestContent);
422 if (bIsUrlEncoded)
423 {
424 // The '+' encodes for a space, so decode it within the string
425 for (char * pChar = requestContent; (pChar = strchr(pChar, '+')) != NULL; )
426 *pChar = ' '; // Found a '+' so replace with a space
427 }
428 }
429
430 return eMethod;
431}
432
433// Read the first line of the HTTP request, setting Uri Index and returning the method type.
434// If it is a GET method then we set the requestContent to whatever follows the '?'. For a other
435// methods there is no content except it may get set later, after the headers for a POST method.
436MethodType readRequestLine(EthernetClient & client, BUFFER & readBuffer, int & nUriIndex, BUFFER & requestContent)
437{
438 MethodType eMethod;
439 // Get first line of request:
440 // Request-Line = Method SP Request-URI SP HTTP-Version CRLF
441 getNextHttpLine(client, readBuffer);
442 // Split it into the 3 tokens
443 char * pMethod = strtok(readBuffer, pSpDelimiters);
444 char * pUri = strtok(NULL, pSpDelimiters);
445 char * pVersion = strtok(NULL, pSpDelimiters);
446 // URI may optionally comprise the URI of a queryable object a '?' and a query
447 // see http://www.ietf.org/rfc/rfc1630.txt
448 strtok(pUri, "?");
449 char * pQuery = strtok(NULL, "?");
450 if (pQuery != NULL)
451 {
452 strcpy(requestContent, pQuery);
453 // The '+' encodes for a space, so decode it within the string
454 for (pQuery = requestContent; (pQuery = strchr(pQuery, '+')) != NULL; )
455 *pQuery = ' '; // Found a '+' so replace with a space
456
457// Serial.print("Get query string: ");
458// Serial.println(requestContent);
459 }
460 if (strcmp(pMethod, "GET") == 0){
461 eMethod = MethodGet;
462#ifdef DEBUG
463 Serial.println("readRequestLine-> GET");
464#endif
465}
466 else if (strcmp(pMethod, "POST") == 0){
467 eMethod = MethodPost;
468#ifdef DEBUG
469 Serial.println("readRequestLine-> POST");
470#endif
471}
472 else if (strcmp(pMethod, "HEAD") == 0){
473 eMethod = MethodHead;
474 #ifdef DEBUG
475 Serial.println("readRequestLine-> HEAD");
476 #endif
477 }
478 else
479 eMethod = MethodUnknown;
480
481 // See if we recognize the URI and get its index
482 nUriIndex = GetUriIndex(pUri);
483
484 return eMethod;
485}
486
487// Read each header of the request till we get the terminating CRLF
488void readRequestHeaders(EthernetClient & client, BUFFER & readBuffer, int & nContentLength, bool & bIsUrlEncoded)
489{
490 nContentLength = 0; // Default is zero in cate there is no content length.
491 bIsUrlEncoded = true; // Default encoding
492 // Read various headers, each terminated by CRLF.
493 // The CRLF gets removed and the buffer holds each header as a string.
494 // An empty header of zero length terminates the list.
495 do
496 {
497 getNextHttpLine(client, readBuffer);
498 // Serial.println(readBuffer); // DEBUG
499 // Process a header. We only need to extract the (optionl) content
500 // length for the binary content that follows all these headers.
501 // General-Header = Date | Pragma
502 // Request-Header = Authorization | From | If-Modified-Since | Referer | User-Agent
503 // Entity-Header = Allow | Content-Encoding | Content-Length | Content-Type
504 // | Expires | Last-Modified | extension-header
505 // extension-header = HTTP-header
506 // HTTP-header = field-name ":" [ field-value ] CRLF
507 // field-name = token
508 // field-value = *( field-content | LWS )
509 // field-content = <the OCTETs making up the field-value
510 // and consisting of either *TEXT or combinations
511 // of token, tspecials, and quoted-string>
512 char * pFieldName = strtok(readBuffer, pSpDelimiters);
513 char * pFieldValue = strtok(NULL, pSpDelimiters);
514
515 if (strcmp(pFieldName, "Content-Length:") == 0)
516 {
517 nContentLength = atoi(pFieldValue);
518 }
519 else if (strcmp(pFieldName, "Content-Type:") == 0)
520 {
521 if (strcmp(pFieldValue, "application/x-www-form-urlencoded") != 0)
522 bIsUrlEncoded = false;
523 }
524 } while (strlen(readBuffer) > 0); // empty string terminates
525}
526
527// Read the entity body of given length (after all the headers) into the buffer.
528void readEntityBody(EthernetClient & client, int nContentLength, BUFFER & content)
529{
530 int i;
531 char c;
532
533 if (nContentLength >= sizeof(content))
534 nContentLength = sizeof(content) - 1; // Should never happen!
535
536 for (i = 0; i < nContentLength; ++i)
537 {
538 c = client.read();
539// Serial.print(c); // DEBUG
540 content[i] = c;
541 }
542
543 content[nContentLength] = 0; // Null string terminator
544
545// Serial.print("Content: ");
546// Serial.println(content);
547}
548
549// See if we recognize the URI and get its index; or -1 if we don't recognize it.
550int GetUriIndex(char * pUri)
551{
552
553#ifdef DEBUG
554 Serial.print("GetUriIndex(");
555 Serial.print(pUri);
556 Serial.print(")\n");
557#endif
558
559 int nUriIndex = -1;
560 // select the page from the buffer (GET and POST) [start]
561 for (int i = 0; i < NUM_URIS; i++)
562 {
563 if (strcmp_P(pUri, (PGM_P)pgm_read_word(&(http_uris[i]))) == 0)
564 {
565 nUriIndex = i;
566
567#ifdef DEBUG
568 Serial.print(" o- URI: ");
569 Serial.println(pUri);
570#endif
571
572 break;
573 }
574 }
575// Serial.print("URI: ");
576// Serial.print(pUri);
577// Serial.print(" Page: ");
578// Serial.println(nUriIndex);
579
580 return nUriIndex;
581}
582
583/**********************************************************************************************************************
584* Read the next HTTP header record which is CRLF delimited. We replace CRLF with string terminating null.
585***********************************************************************************************************************/
586void getNextHttpLine(EthernetClient & client, BUFFER & readBuffer)
587{
588 char c;
589 int bufindex = 0; // reset buffer
590
591 // reading next header of HTTP request
592 if (client.connected() && client.available())
593 {
594 // read a line terminated by CRLF
595 readBuffer[0] = client.read();
596 readBuffer[1] = client.read();
597 bufindex = 2;
598 for (int i = 2; readBuffer[i - 2] != '\r' && readBuffer[i - 1] != '\n'; ++i)
599 {
600 // read full line and save it in buffer, up to the buffer size
601 c = client.read();
602 if (bufindex < sizeof(readBuffer))
603 readBuffer[bufindex++] = c;
604 }
605 readBuffer[bufindex - 2] = 0; // Null string terminator overwrites '\r'
606 }
607}
608
609/**********************************************************************************************************************
610* Send Pages
611 Full-Response = Status-Line
612 *( General-Header
613 | Response-Header
614 | Entity-Header )
615 CRLF
616 [ Entity-Body ]
617
618 Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
619 General-Header = Date | Pragma
620 Response-Header = Location | Server | WWW-Authenticate
621 Entity-Header = Allow | Content-Encoding | Content-Length | Content-Type
622 | Expires | Last-Modified | extension-header
623*
624***********************************************************************************************************************/
625void sendPage(EthernetClient & client, int nUriIndex, BUFFER & requestContent)
626{
627
628#ifdef DEBUG
629 Serial.print("sendPage(");
630 Serial.print(nUriIndex); Serial.print(", ");
631 Serial.print(requestContent);
632 Serial.println(")");
633#endif
634
635 if (strncmp(requestContent, "Button1=", 8) == 0){
636 //Action1(strncmp(&requestContent[9], "true", 4) == 0);
637 MoveTo(0, _EndPoint, 255);
638 }
639 else if (strncmp(requestContent, "Button2=", 8) == 0){
640 //Action2(strncmp(&requestContent[9], "true", 4) == 0);
641 MoveTo(0, _StartPoint, 255);
642 }
643 else if (strncmp(requestContent, "Button3=", 8) == 0){
644 //Action3(strncmp(&requestContent[9], "true", 4) == 0);
645 MoveTo(1, _EndPoint, 255);
646 }
647 else if (strncmp(requestContent, "Button4=", 8) == 0){
648 //Action4(strncmp(&requestContent[9], "true", 4) == 0);
649 MoveTo(1, _StartPoint, 255);
650 }
651 else if (strncmp(requestContent, "Button5=", 8) == 0){
652 MoveTo(1, _StartPoint, 255);
653 delay(100);
654 MoveTo(0, _StartPoint, 255);
655 }
656 else if (strncmp(requestContent, "Button6=", 8) == 0){
657 MoveTo(0, _EndPoint, 255);
658 delay(100);
659 MoveTo(1, _EndPoint, 255);
660 }
661#ifdef DEBUG
662 else if (strncmp(requestContent, "", 1) == 0)
663 Serial.print("-> Refresh\n");
664 else
665 Serial.print("-> not recognized\n");
666#endif
667
668 // send HTML header
669 // sendProgMemAsString(client,(char*)pgm_read_word(&(contents_main[CONT_HEADER])));
670 sendProgMemAsString(client, (char*)pgm_read_word(&(contents_main[CONT_TOP])));
671
672 // send menu
673 sendProgMemAsString(client, (char*)pgm_read_word(&(contents_main[CONT_MENU])));
674
675 // send title
676 sendProgMemAsString(client, (char*)pgm_read_word(&(contents_titles[nUriIndex])));
677
678 // send the body for the requested page
679 sendUriContentByIndex(client, nUriIndex, requestContent);
680
681 // Append the data sent in the original HTTP request
682 client.print("<br/>");
683 // send POST variables
684 client.print(requestContent);
685
686 // send footer
687 sendProgMemAsString(client,(char*)pgm_read_word(&(contents_main[CONT_FOOTER])));
688}
689
690/**********************************************************************************************************************
691* Send Images
692***********************************************************************************************************************/
693void sendImage(EthernetClient & client, int nUriIndex, BUFFER & requestContent)
694{
695 int nImageIndex = nUriIndex - NUM_PAGES;
696
697 // send the header for the requested image
698 sendUriContentByIndex(client, nUriIndex, requestContent);
699
700 // send the image data
701 sendProgMemAsBinary(client, (char *)pgm_read_word(&(data_for_images[nImageIndex])), (int)pgm_read_word(&(size_for_images[nImageIndex])));
702}
703
704/**********************************************************************************************************************
705* Send content split by buffer size
706***********************************************************************************************************************/
707// If we provide string data then we don't need specify an explicit size and can do a string copy
708void sendProgMemAsString(EthernetClient & client, const char *realword)
709{
710 sendProgMemAsBinary(client, realword, strlen_P(realword));
711}
712
713// Non-string data needs to provide an explicit size
714void sendProgMemAsBinary(EthernetClient & client, const char* realword, int realLen)
715{
716 int remaining = realLen;
717 const char * offsetPtr = realword;
718 int nSize = sizeof(BUFFER);
719 BUFFER buffer;
720
721 while (remaining > 0)
722 {
723 // print content
724 if (nSize > remaining)
725 nSize = remaining; // Partial buffer left to send
726
727 memcpy_P(buffer, offsetPtr, nSize);
728
729 if (client.write((const uint8_t *)buffer, nSize) != nSize)
730 Serial.println("Failed to send data");
731
732 // more content to print?
733 remaining -= nSize;
734 offsetPtr += nSize;
735 }
736}
737
738/**********************************************************************************************************************
739* Send real page content
740***********************************************************************************************************************/
741// This method takes the contents page identified by nUriIndex, divides it up into buffer-sized
742// strings, passes it on for STX substitution and finally sending to the client.
743void sendUriContentByIndex(EthernetClient client, int nUriIndex, BUFFER & requestContent)
744{
745 // Locate the page data for the URI and prepare to process in buffer-sized chunks.
746 const char * offsetPtr; // Pointer to offset within URI for data to be copied to buffer and sent.
747 char *pNextString;
748 int nSubstituteIndex = -1; // Count of substitutions so far for this URI
749 int remaining; // Total bytes (of URI) remaining to be sent
750 int nSize = sizeof(BUFFER) - 1; // Effective size of buffer allowing last char as string terminator
751 BUFFER buffer;
752
753 if (nUriIndex < NUM_PAGES)
754 offsetPtr = (char*)pgm_read_word(&(contents_pages[nUriIndex]));
755 else
756 offsetPtr = (char*)pgm_read_word(&(image_header));
757
758 buffer[nSize] = 0; // ensure there is always a string terminator
759 remaining = strlen_P(offsetPtr); // Set total bytes of URI remaining
760
761 while (remaining > 0)
762 {
763 // print content
764 if (nSize > remaining)
765 {
766 // Set whole buffer to string terminator before copying remainder.
767 memset(buffer, 0, STRING_BUFFER_SIZE);
768 nSize = remaining; // Partial buffer left to send
769 }
770 memcpy_P(buffer, offsetPtr, nSize);
771 offsetPtr += nSize;
772 // We have a buffer's worth of page to check for substitution markers/delimiters.
773 // Scan the buffer for markers, dividing it up into separate strings.
774 if (buffer[0] == *pStxDelimiter) // First char is delimiter
775 {
776 sendSubstitute(client, nUriIndex, ++nSubstituteIndex, requestContent);
777 --remaining;
778 }
779 // First string is either terminated by the null at the end of the buffer
780 // or by a substitution delimiter. So simply send it to the client.
781 pNextString = strtok(buffer, pStxDelimiter);
782 client.print(pNextString);
783 remaining -= strlen(pNextString);
784 // Scan for strings between delimiters
785 for (pNextString = strtok(NULL, pStxDelimiter); pNextString != NULL && remaining > 0; pNextString = strtok(NULL, pStxDelimiter))
786 {
787 // pNextString is pointing to the next string AFTER a delimiter
788 sendSubstitute(client, nUriIndex, ++nSubstituteIndex, requestContent);
789 --remaining;
790 client.print(pNextString);
791 remaining -= strlen(pNextString);
792 }
793 }
794}
795
796// Call this method in response to finding a substitution character '\002' within some
797// URI content to send the appropriate replacement text, depending on the URI index and
798// the substitution index within the content.
799void sendSubstitute(EthernetClient client, int nUriIndex, int nSubstituteIndex, BUFFER & requestContent)
800{
801#ifdef DEBUG
802 Serial.print("sendSubstitute(");
803 Serial.print(nUriIndex); Serial.print(", ");
804 Serial.print(nSubstituteIndex); Serial.print(", ");
805 Serial.print(requestContent);
806 Serial.print(")\n");
807#endif
808 if (nUriIndex < NUM_PAGES)
809 {
810 // Page request
811 switch (nUriIndex)
812 {
813 case 1: // page 2
814#ifdef DEBUG
815 Serial.println(" -> Case 1");
816#endif
817 if (nSubstituteIndex < 4){
818 //client.print("<b>");
819 client.print(_currentValue[nSubstituteIndex/2]);
820 //client.print("</b>");
821 }
822 else if ( (nSubstituteIndex >= 4) &&
823 (nSubstituteIndex < 8) ) {
824 //client.print("<b>");
825 client.print(_sensorValue[nSubstituteIndex/2-2]);
826 //client.print("</b>");
827 }
828 else if ( (nSubstituteIndex >= 8) &&
829 (nSubstituteIndex < 12) ) {
830 //client.print("<b>");
831 client.print(_StatusLabel[_LidStatus[nSubstituteIndex/2-4]]);
832 //client.print("</b>");
833
834 }
835 break;
836 case 2: // page 3
837 Serial.println(" -> Case 2");
838//
839// switch (nSubstituteIndex)
840// {
841// case 0: // LedOn button send value
842//#ifdef DEBUG
843// Serial.println(requestContent);
844//#endif
845// if (strncmp(requestContent, "Button1=", 8) == 0)
846// Action1(strncmp(&requestContent[9], "true", 4) == 0);
847//
848// client.print(Action1 ? "false" : "true");
849// break;
850// case 1: // LedOn button legend
851// //client.print(isLedOn ? "Off" : "On");
852// break;
853// case 2: // LedOn partial image name
854// //client.print(isLedOn ? "on" : "off");
855// break;
856// default:
857// break;
858// }
859 break;
860 }
861 }
862 else
863 {
864 // Image request
865 int nImageIndex = nUriIndex - NUM_PAGES;
866
867 switch (nSubstituteIndex)
868 {
869 case 0:
870 // Content-Length value - ie. image size
871 char strSize[6]; // Up to 5 digits plus null terminator
872 itoa((int)pgm_read_word(&(size_for_images[nImageIndex])), strSize, 10);
873 //Serial.println(strSize); // Debug
874 client.print(strSize);
875 break;
876 case 1:
877 // Content-Type partial value
878 switch (nImageIndex)
879 {
880 case 0: // favicon
881 client.print("x-icon");
882 break;
883 case 1: // led on image
884 case 2: // led off image
885 client.print("png");
886 break;
887 }
888 }
889 }
890}
891#endif
892//
893//void Action1(bool argument)
894//{
895// Serial.print("Action->Action1(");
896// Serial.print(argument);
897// Serial.print(")\n");
898//
899// // Move motor 0 out
900// int m=0;
901// MoveTo(m, 1023, 200);
902//
903//}
904
905//void Action2(bool argument)
906//{
907// Serial.print("Action->Action2(");
908// Serial.print(argument);
909// Serial.print(")\n");
910//
911// // Move motor 1 out
912// int m=0;
913// MoveTo(m, 0, 200);
914//}
915//
916//void Action3(bool argument)
917//{
918// Serial.print("Action->Action3(");
919// Serial.print(argument);
920// Serial.print(")\n");
921//
922// // Move motor 0 in
923// int m=1;
924// MoveTo(m, 1023, 200);
925//}
926//
927//void Action4(bool argument)
928//{
929// Serial.print("Action->Action4(");
930// Serial.print(argument);
931// Serial.print(")\n");
932//
933// // Move motor 1 in
934// int m=1;
935// MoveTo(m, 0, 200);
936//}
937//
938// position in [%]-> [0-1] Closed-Open
939//
940void MoveTo(int motor, double target_position, int mySpeed){
941
942 // define tmp value for the speed
943 int speedTmp = 0;
944
945 // define variable containing the current actuator position
946 // the travel to be done to rech the target position and the
947 // motor current
948 double current_position;
949 double err_current_position;
950
951 double original_position;
952 double err_original_position;
953
954 double motor_current;
955 double err_motor_current;
956
957 double travel;
958
959 // only one reading to define the position is not sufficient
960 // current_position = ReadSensor(motor);
961
962 // Calculate average final position
963 double tmp=0;
964 double tmpM=0;
965 double tmpS=0;
966 int steps=0;
967
968 for (int i=0;i<SAMPLES;i++){
969 tmp=ReadSensor(motor);
970 tmpM += tmp;
971 tmpS += tmp*tmp;
972 }
973 tmpM /= SAMPLES;
974 tmpS = sqrt(tmpS/SAMPLES - tmpM*tmpM);
975
976 Serial.print(" - The current position of the actuator is ");
977 Serial.print(tmpM,3);
978 Serial.print( " +/- " );
979 Serial.println(tmpS,3);
980
981 int tmpS_int = (int) tmpS;
982
983 // round the mean to it to the closest integer
984 current_position = (int) (tmpM+0.5);
985 if (((int)tmpS) < 1){
986 err_current_position = 1.;
987 }
988 else{
989 err_current_position = tmpS;
990 }
991
992 original_position = current_position;
993 err_original_position = err_current_position;
994
995 Serial.print(" - The corrected position of the actuator is ");
996 Serial.print(current_position);
997 Serial.print( " +/- " );
998 Serial.println(err_current_position);
999
1000
1001 // calculate the travel needed to reach the target position
1002 travel = target_position - current_position;
1003
1004 Serial.print("Moving motor ");
1005 Serial.print(motor);
1006 Serial.print(" from pos. ");
1007 Serial.print(current_position,3);
1008 Serial.print(" to position ");
1009 Serial.print(target_position,3);
1010 Serial.print(" - Travel distance = ");
1011 Serial.print(travel,3);
1012
1013 // [IF] the travel is bigger than +2*(absolute position error) try to move out the motor
1014 if (travel > 2*err_current_position){
1015 // Try to place here (if you have time) a speed self adjucting algorithm
1016 // base on the trave which the actuator has still to do
1017 if( _LidStatus[motor] != _CLOSED){
1018
1019 Serial.println(" - going out (lid closing)");
1020 speedTmp = mySpeed; // positive speed
1021 steps++;
1022 _LidStatus[motor] = _CLOSING;
1023
1024 // Accelerate motor from 0 to speedTmp linearly
1025 for (int j=0;j<speedTmp;j++){
1026 Motor(motor, j);
1027 delay(1);
1028 }
1029 }
1030 else{
1031 Serial.println(" - already closed");
1032
1033 _LidStatus[motor] = _CLOSED;
1034 return;
1035 }
1036 }
1037 // [ELSE IF] travel is between -2*(absolute position error) and +2*(absolute position error)
1038 // consider yourself already in position
1039 else if (travel <= 2*err_current_position &&
1040 travel >= -2*err_current_position ){
1041 Serial.println(" - already in place");
1042
1043 _LidStatus[motor] = _STEADY;
1044 return;
1045 // already in place don't bother moving more.
1046 }
1047 // [ELSE} if the travel is smaller than -2*(absolute position error) try to move in the motor
1048 else{
1049 Serial.println(" - going in (lid opening)");
1050 speedTmp = -mySpeed; // negative speed
1051 steps++;
1052 _LidStatus[motor] = _OPENING;
1053
1054 // Accelerate motor from 0 to -speedTmp linearly
1055 for (int j=0;j>speedTmp;j--){
1056 Motor(motor, j);
1057 delay(1);
1058 }
1059 }
1060
1061
1062 // Start the main loop which checks the motors while they are mooving
1063 tmp=0;
1064 tmpM=0;
1065 tmpS=0;
1066 for (steps=1;abs(travel) != 0 ;steps++){
1067 //Read Current
1068 motor_current = ReadCurrentM(motor,10);
1069
1070 // If Overcurrent stop
1071 if (motor_current > _OverCurrent){
1072 Motor(motor, 0); // Stop Motor
1073
1074 Serial.print(" - WARNING!!! Overcurrent ");
1075 Serial.print(motor_current,3);
1076 Serial.print(" [A] at position ");
1077 Serial.println(current_position,3);
1078
1079 _LidStatus[motor] = _OVER_CURRENT;
1080 return;
1081 }
1082
1083 // If Fault stop
1084 if (getFault(motor)){
1085 Motor(motor, 0); // Stop Motor
1086 Serial.print(" - GetFault - at position ");
1087 Serial.println(current_position,3);
1088 _LidStatus[motor] = _MOTOR_FAULT;
1089 break;
1090 }
1091
1092 // Average Current around the steps
1093 tmp = motor_current;
1094 tmpM += tmp;
1095 tmpS += tmp*tmp;
1096
1097 // Read current position
1098 // it doesn't make sense to read it here more time as the actuars are moving
1099 current_position = ReadSensorM(motor,10);
1100
1101 // Calculate travel distance
1102 travel = target_position - current_position;
1103
1104 // Read current absorbed the motor and append the values for the calculation
1105 // of the mean value and its error
1106
1107
1108 // [IF] the current drops below ~0.07 A might means that the end swirch
1109 // stopped the motor check also the position to determine if this is true.
1110 if (motor_current < _ZeroCurrent){
1111 // Closing
1112 if ( current_position > _EndPointLimit && target_position > _EndPointLimit ){
1113 Serial.print(" - Reached End of Actuator. Pos = ");
1114 Serial.println(current_position, 3);
1115
1116 _LidStatus[motor] = _CLOSED;
1117 break; //Exit from the for loop
1118 }
1119 // Opening
1120 else if (current_position < _StartPointLimit && target_position < _StartPointLimit ){
1121 Serial.print(" - Reached Beginning of Actuator. Pos = ");
1122 Serial.println(current_position, 3);
1123
1124 _LidStatus[motor] = _OPEN;
1125 break; //Exit from the for loop
1126 }
1127 // Error
1128 else {
1129 Serial.print(" - Error!! No current in motor ");
1130 Serial.print(motor);
1131 Serial.print(". I= ");
1132 Serial.print(motor_current);
1133 Serial.print("A . Pos = ");
1134 Serial.println(current_position, 3);
1135
1136 _LidStatus[motor] = _POWER_PROBLEM;
1137 break; //Exit from the for loop
1138 }
1139 }
1140
1141 if (_LidStatus[motor] == _CLOSING && motor_current > _CurrentPushingLimit && current_position > _EndPointLimit){
1142 Serial.print(" - step ");
1143 Serial.print(steps);
1144 // double travel_done= (55. * (target_position - original_position))/1024.;
1145 // Serial.print(" - travelled for ");
1146 // Serial.print(travel_done);
1147 Serial.print(" - pushing -> I = ");
1148 Serial.print(motor_current, 3);
1149 Serial.println(" A");
1150 _LidStatus[motor] = _CLOSED;
1151 break;
1152 }
1153
1154 // If too many cycles of the loop print a message and check the position and the current
1155 if (steps %50 == 0){
1156 Serial.print(" - step ");
1157 Serial.print(steps);
1158 Serial.print(" - still in loop. Pos = ");
1159 Serial.print(current_position, 3);
1160 Serial.print(" - Istantaneous current = ");
1161 Serial.print(motor_current, 3);
1162 Serial.print(" A");
1163 Serial.print(" - Average current = ");
1164 Serial.print(tmpM/steps, 3);
1165 Serial.println(" A");
1166
1167
1168 if( _LidStatus[motor] != _CLOSING &&
1169 _LidStatus[motor] != _OPENING)
1170 _LidStatus[motor] = _MOVING;
1171
1172 // Redefine better those limits... they might not be necessary with the new low
1173 // current limits
1174 //if (steps %500 && current_position > 1000 && target_position > 1000 ){
1175 // Serial.print(" - Reached End of Actuator. Pos = ");
1176 // Serial.println(current_position, 3);
1177 // break;
1178 //}
1179 //if (steps %500 && current_position < 80 && target_position < 80 ){
1180 // Serial.print(" - Reached Beginning of Actuator. Pos = ");
1181 // Serial.println(current_position, 3);
1182 // break;
1183 //}
1184 }
1185
1186
1187
1188 // minimum delay between a cycle and the other is 1 ms
1189 delay (10);
1190 }
1191
1192 // At this stage the motor should be stopped in any case
1193 Motor(motor, 0);
1194 Serial.print(" - motor reached the destination - pos. ");
1195 Serial.println(current_position,3);
1196
1197 // Calculate current average and sigma
1198 tmpM /= steps;
1199 tmpS = sqrt(tmpS/steps - tmpM*tmpM);
1200 Serial.print(" - average current over the loop ");
1201 Serial.print(tmpM,3);
1202 Serial.print( " +/- " );
1203 Serial.println(tmpS,3);
1204
1205 // Wait 100 ms then calculate average final position
1206 delay(100);
1207 tmp=0; tmpM=0; tmpS=0;
1208
1209 for (int i=0;i<SAMPLES;i++){
1210 tmp=ReadSensor(motor);
1211 tmpM += tmp;
1212 tmpS += tmp*tmp;
1213 }
1214 tmpM /= SAMPLES;
1215 tmpS = sqrt(tmpS/SAMPLES - tmpM*tmpM);
1216
1217 Serial.print(" - final position is ");
1218 Serial.print(tmpM,3);
1219 Serial.print( " +/- " );
1220 Serial.println(tmpS,3);
1221
1222 Serial.print(" - Lid staus is ");
1223 Serial.println(_StatusLabel[_LidStatus[motor]]);
1224
1225 Serial.print("availableMemory()=");
1226 Serial.println(availableMemory());
1227
1228
1229}
1230
1231int availableMemory() {
1232 int free_memory;
1233 if ((int)__brkval==0)
1234 free_memory = ((int)&free_memory) - ((int) &__bss_end);
1235 else
1236 free_memory = ((int)&free_memory) - ((int) &__brkval);
1237
1238 return free_memory;
1239}
1240
1241
1242// ReadSensor(-1); - Read all sensor
1243// ReadSensor(0); - Read sensor 0
1244// ReadSensor(1); - Read sensor 1
1245double ReadSensor(int motor){
1246#ifdef DEBUG
1247 Serial.println("Action->ReadSensors()");
1248#endif
1249
1250 switch (motor){
1251 case -1: // Read all of them
1252 _sensorValue[0] = analogRead(A2);//*_ADC2V - _Voffset;// *_Compensation; // Actuator 1 position
1253 _sensorValue[1] = analogRead(A3);//*_ADC2V - _Voffset;// *_Compensation; // Actuator 2 position
1254 return -1;
1255 case 0:
1256 _sensorValue[motor] = analogRead(A2);//*_ADC2V - _Voffset; //*_Compensation;
1257 return _sensorValue[motor]; // Actuator 1 position
1258 case 1:
1259 _sensorValue[motor] = analogRead(A3);//*_ADC2V - _Voffset;//_Compensation;
1260 return _sensorValue[motor]; // Actuator 1 position
1261 }
1262}
1263
1264double ReadSensorM(int motor, int samples){
1265#ifdef DEBUG
1266 Serial.println("Action->ReadSensorsM()");
1267#endif
1268 _sensorValue[motor]=0;
1269 switch (motor){
1270 case 0:
1271 for (int j=0;j<samples;j++)
1272 _sensorValue[motor] += analogRead(A2);//*_ADC2V - _Voffset; //*_Compensation;
1273 case 1:
1274 for (int j=0;j<samples;j++)
1275 _sensorValue[motor] += analogRead(A3);//*_ADC2V - _Voffset;//_Compensation;
1276 }
1277
1278 _sensorValue[motor] /= samples;
1279 return _sensorValue[motor]; // Actuator 1 position
1280}
1281
1282
1283// ReadCurrent(-1); - Read current for all the motors
1284// ReadCurrent(0); - Read motor 0 current
1285// ReadCurrent(1); - Read motor 1 current
1286double ReadCurrent(int motor){
1287 switch (motor){
1288 case -1: // Read all of them
1289 _currentValue[0] = analogRead(A4)*_ADC2V/(_V2A*10.);
1290 _currentValue[1] = analogRead(A5)*_ADC2V/(_V2A*10.);
1291 Serial.println("Action->ReadSensors()");
1292 return -1;
1293 case 0:
1294 _currentValue[motor] = analogRead(A4)*_ADC2V/(_V2A*10.);
1295 return _currentValue[motor]; // Current of the motor
1296 case 1:
1297 _currentValue[motor] = analogRead(A5)*_ADC2V/(_V2A*10.);
1298 return _currentValue[motor]; // Current of the motor
1299 }
1300}
1301
1302double ReadCurrentM(int motor, int samples){
1303 _currentValue[motor] = 0;
1304 switch (motor){
1305 case 0:
1306 for (int j=0;j<samples;j++)
1307 _currentValue[motor] += analogRead(A4)*_ADC2V/(_V2A*10.);
1308 case 1:
1309 for (int j=0;j<samples;j++)
1310 _currentValue[motor] += analogRead(A5)*_ADC2V/(_V2A*10.);
1311 }
1312 _currentValue[motor]/=samples;
1313 return _currentValue[motor];
1314
1315}
1316
1317
1318// Return error status for motor
1319unsigned char getFault(int motor)
1320{
1321 return 0; //!digitalRead(_ENDIAG[motor]);
1322}
1323
1324// control motor, -255 < pwm < 255
1325//
1326void Motor(int motor, int pwm){
1327 bool reverse = false;
1328
1329 // Check sign and direction
1330 if (pwm < 0){
1331 pwm = -pwm;
1332 reverse = true;
1333 }
1334
1335 // Check max speed
1336 if (pwm > 255) pwm = 255;
1337 else if (pwm < -255) pwm = -255;
1338
1339 // Activate motors
1340 analogWrite(_pinPWM[motor], pwm); //set pwm control, 0 for stop, and 255 for maximum speed
1341 if (pwm != 0){
1342 if(reverse) {
1343 digitalWrite(_pinDA[motor], HIGH);
1344 digitalWrite(_pinDB[motor], LOW);
1345 }
1346 else {
1347 digitalWrite(_pinDA[motor], LOW);
1348 digitalWrite(_pinDB[motor], HIGH);
1349 }
1350 }
1351 else {
1352 digitalWrite(_pinDA[motor], LOW);
1353 digitalWrite(_pinDB[motor], LOW);
1354 }
1355}
1356
1357
Note: See TracBrowser for help on using the repository browser.