source: firmware/ShutterController/ShutterController.ino@ 20110

Last change on this file since 20110 was 14778, checked in by boccone, 12 years ago
trying to release current and position contrain to solve the non-closing issue of the last days
File size: 50.7 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//byte _mac[] = { 0x80, 0x49, 0x71, 0x0f, 0x80, 0xd0 };
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.75; // 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 = 775; // This must me 740 for the mockup and >770 for the FACT shutter
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 counts </span><p/><span id=\"pos2\" value=\"\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
280
281 server.begin();
282#endif
283 //_Motor.init();
284
285 //For Arduino Motor Shield set pin 4,5,6,7 to output mode
286 pinMode(2, OUTPUT);
287 pinMode(4, OUTPUT);
288 pinMode(5, OUTPUT);
289 pinMode(6, OUTPUT);
290 pinMode(7, OUTPUT);
291 pinMode(8, OUTPUT);
292
293 pinMode(A0, INPUT); //
294 pinMode(A1, INPUT); //
295 pinMode(A2, INPUT); //
296 pinMode(A3, INPUT); //
297
298 // First clear all three prescaler bits:
299 int prescalerVal = 0x07; // create a variable called prescalerVal and set it equal to the binary number "00000111"
300
301 TCCR0B &= ~prescalerVal; // AND the value in TCCR0B with binary number "11111000"
302
303 //Now set the appropriate prescaler bits:
304 prescalerVal = 3; // set prescalerVal equal to binary number "00000001"
305 TCCR0B |= prescalerVal; // OR the value in TCCR0B with binary number "00000001"
306
307 // TCCR0A = _BV(COM0A0) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
308 // TCCR0B = _BV(WGM02) | _BV(CS02);
309 // OCR0A = 180;
310 // OCR0B = 50;
311
312 //pinMode(ledPin, OUTPUT);
313 //setLed(true);
314}
315
316/**********************************************************************************************************************
317* Main loop
318***********************************************************************************************************************/
319
320void loop()
321{
322#ifdef ENABLE_ETHERNET
323 EthernetClient client = server.available();
324#endif
325
326
327#ifdef ENABLE_ETHERNET
328 if (client)
329 {
330 // now client is connected to arduino we need to extract the
331 // following fields from the HTTP request.
332 int nUriIndex; // Gives the index into table of recognized URIs or -1 for not found.
333 BUFFER requestContent; // Request content as a null-terminated string.
334 MethodType eMethod = readHttpRequest(client, nUriIndex, requestContent);
335
336#ifdef DEBUG
337 Serial.print(" o- Read Request type: ");
338 Serial.print(eMethod);
339 Serial.print(" Uri index: ");
340 Serial.print(nUriIndex);
341 Serial.print(" content: ");
342 Serial.print(requestContent);
343 Serial.print("\n");
344#endif
345 if (nUriIndex < 0)
346 {
347 // URI not found
348 sendProgMemAsString(client, (char*)pgm_read_word(&(page_404[0])));
349 }
350 else if (nUriIndex < NUM_PAGES)
351 {
352 // Normal page request, may depend on content of the request
353#ifdef DEBUG
354 Serial.println(" o- Sending page");
355#endif
356 sendPage(client, nUriIndex, requestContent);
357 }
358 else
359 {
360 // Image request
361 sendImage(client, nUriIndex, requestContent);
362 }
363
364 // give the web browser time to receive the data
365 // delay(1);
366 delay(100);
367
368 client.stop();
369 }
370#endif
371
372
373}
374
375#ifdef ENABLE_ETHERNET
376/**********************************************************************************************************************
377* Method for read HTTP Header Request from web client
378*
379* The HTTP request format is defined at http://www.w3.org/Protocols/HTTP/1.0/spec.html#Message-Types
380* and shows the following structure:
381* Full-Request and Full-Response use the generic message format of RFC 822 [7] for transferring entities. Both messages may include optional header fields
382* (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).
383* Full-Request = Request-Line
384* *( General-Header
385* | Request-Header
386* | Entity-Header )
387* CRLF
388* [ Entity-Body ]
389*
390* 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.
391* No CR or LF are allowed except in the final CRLF sequence.
392* Request-Line = Method SP Request-URI SP HTTP-Version CRLF
393* HTTP header fields, which include General-Header, Request-Header, Response-Header, and Entity-Header fields, follow the same generic format.
394* Each header field consists of a name followed immediately by a colon (":"), a single space (SP) character, and the field value.
395* 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.
396* HTTP-header = field-name ":" [ field-value ] CRLF
397***********************************************************************************************************************/
398// Read HTTP request, setting Uri Index, the requestContent and returning the method type.
399MethodType readHttpRequest(EthernetClient & client, int & nUriIndex, BUFFER & requestContent)
400{
401
402
403 BUFFER readBuffer; // Just a work buffer into which we can read records
404 int nContentLength = 0;
405 bool bIsUrlEncoded;
406
407 requestContent[0] = 0; // Initialize as an empty string
408 // Read the first line: Request-Line setting Uri Index and returning the method type.
409 MethodType eMethod = readRequestLine(client, readBuffer, nUriIndex, requestContent);
410 // Read any following, non-empty headers setting content length.
411 readRequestHeaders(client, readBuffer, nContentLength, bIsUrlEncoded);
412
413 if (nContentLength > 0)
414 {
415 // If there is some content then read it and do an elementary decode.
416 readEntityBody(client, nContentLength, requestContent);
417 if (bIsUrlEncoded)
418 {
419 // The '+' encodes for a space, so decode it within the string
420 for (char * pChar = requestContent; (pChar = strchr(pChar, '+')) != NULL; )
421 *pChar = ' '; // Found a '+' so replace with a space
422 }
423 }
424
425 return eMethod;
426}
427
428// Read the first line of the HTTP request, setting Uri Index and returning the method type.
429// If it is a GET method then we set the requestContent to whatever follows the '?'. For a other
430// methods there is no content except it may get set later, after the headers for a POST method.
431MethodType readRequestLine(EthernetClient & client, BUFFER & readBuffer, int & nUriIndex, BUFFER & requestContent)
432{
433 MethodType eMethod;
434 // Get first line of request:
435 // Request-Line = Method SP Request-URI SP HTTP-Version CRLF
436 getNextHttpLine(client, readBuffer);
437 // Split it into the 3 tokens
438 char * pMethod = strtok(readBuffer, pSpDelimiters);
439 char * pUri = strtok(NULL, pSpDelimiters);
440 char * pVersion = strtok(NULL, pSpDelimiters);
441 // URI may optionally comprise the URI of a queryable object a '?' and a query
442 // see http://www.ietf.org/rfc/rfc1630.txt
443 strtok(pUri, "?");
444 char * pQuery = strtok(NULL, "?");
445 if (pQuery != NULL)
446 {
447 strcpy(requestContent, pQuery);
448 // The '+' encodes for a space, so decode it within the string
449 for (pQuery = requestContent; (pQuery = strchr(pQuery, '+')) != NULL; )
450 *pQuery = ' '; // Found a '+' so replace with a space
451
452// Serial.print("Get query string: ");
453// Serial.println(requestContent);
454 }
455 if (strcmp(pMethod, "GET") == 0){
456 eMethod = MethodGet;
457#ifdef DEBUG
458 Serial.println("readRequestLine-> GET");
459#endif
460}
461 else if (strcmp(pMethod, "POST") == 0){
462 eMethod = MethodPost;
463#ifdef DEBUG
464 Serial.println("readRequestLine-> POST");
465#endif
466}
467 else if (strcmp(pMethod, "HEAD") == 0){
468 eMethod = MethodHead;
469 #ifdef DEBUG
470 Serial.println("readRequestLine-> HEAD");
471 #endif
472 }
473 else
474 eMethod = MethodUnknown;
475
476 // See if we recognize the URI and get its index
477 nUriIndex = GetUriIndex(pUri);
478
479 return eMethod;
480}
481
482// Read each header of the request till we get the terminating CRLF
483void readRequestHeaders(EthernetClient & client, BUFFER & readBuffer, int & nContentLength, bool & bIsUrlEncoded)
484{
485 nContentLength = 0; // Default is zero in cate there is no content length.
486 bIsUrlEncoded = true; // Default encoding
487 // Read various headers, each terminated by CRLF.
488 // The CRLF gets removed and the buffer holds each header as a string.
489 // An empty header of zero length terminates the list.
490 do
491 {
492 getNextHttpLine(client, readBuffer);
493 // Serial.println(readBuffer); // DEBUG
494 // Process a header. We only need to extract the (optionl) content
495 // length for the binary content that follows all these headers.
496 // General-Header = Date | Pragma
497 // Request-Header = Authorization | From | If-Modified-Since | Referer | User-Agent
498 // Entity-Header = Allow | Content-Encoding | Content-Length | Content-Type
499 // | Expires | Last-Modified | extension-header
500 // extension-header = HTTP-header
501 // HTTP-header = field-name ":" [ field-value ] CRLF
502 // field-name = token
503 // field-value = *( field-content | LWS )
504 // field-content = <the OCTETs making up the field-value
505 // and consisting of either *TEXT or combinations
506 // of token, tspecials, and quoted-string>
507 char * pFieldName = strtok(readBuffer, pSpDelimiters);
508 char * pFieldValue = strtok(NULL, pSpDelimiters);
509
510 if (strcmp(pFieldName, "Content-Length:") == 0)
511 {
512 nContentLength = atoi(pFieldValue);
513 }
514 else if (strcmp(pFieldName, "Content-Type:") == 0)
515 {
516 if (strcmp(pFieldValue, "application/x-www-form-urlencoded") != 0)
517 bIsUrlEncoded = false;
518 }
519 } while (strlen(readBuffer) > 0); // empty string terminates
520}
521
522// Read the entity body of given length (after all the headers) into the buffer.
523void readEntityBody(EthernetClient & client, int nContentLength, BUFFER & content)
524{
525 int i;
526 char c;
527
528 if (nContentLength >= sizeof(content))
529 nContentLength = sizeof(content) - 1; // Should never happen!
530
531 for (i = 0; i < nContentLength; ++i)
532 {
533 c = client.read();
534// Serial.print(c); // DEBUG
535 content[i] = c;
536 }
537
538 content[nContentLength] = 0; // Null string terminator
539
540// Serial.print("Content: ");
541// Serial.println(content);
542}
543
544// See if we recognize the URI and get its index; or -1 if we don't recognize it.
545int GetUriIndex(char * pUri)
546{
547
548#ifdef DEBUG
549 Serial.print("GetUriIndex(");
550 Serial.print(pUri);
551 Serial.print(")\n");
552#endif
553
554 int nUriIndex = -1;
555 // select the page from the buffer (GET and POST) [start]
556 for (int i = 0; i < NUM_URIS; i++)
557 {
558 if (strcmp_P(pUri, (PGM_P)pgm_read_word(&(http_uris[i]))) == 0)
559 {
560 nUriIndex = i;
561
562#ifdef DEBUG
563 Serial.print(" o- URI: ");
564 Serial.println(pUri);
565#endif
566
567 break;
568 }
569 }
570// Serial.print("URI: ");
571// Serial.print(pUri);
572// Serial.print(" Page: ");
573// Serial.println(nUriIndex);
574
575 return nUriIndex;
576}
577
578/**********************************************************************************************************************
579* Read the next HTTP header record which is CRLF delimited. We replace CRLF with string terminating null.
580***********************************************************************************************************************/
581void getNextHttpLine(EthernetClient & client, BUFFER & readBuffer)
582{
583 char c;
584 int bufindex = 0; // reset buffer
585
586 // reading next header of HTTP request
587 if (client.connected() && client.available())
588 {
589 // read a line terminated by CRLF
590 readBuffer[0] = client.read();
591 readBuffer[1] = client.read();
592 bufindex = 2;
593 for (int i = 2; readBuffer[i - 2] != '\r' && readBuffer[i - 1] != '\n'; ++i)
594 {
595 // read full line and save it in buffer, up to the buffer size
596 c = client.read();
597 if (bufindex < sizeof(readBuffer))
598 readBuffer[bufindex++] = c;
599 }
600 readBuffer[bufindex - 2] = 0; // Null string terminator overwrites '\r'
601 }
602}
603
604/**********************************************************************************************************************
605* Send Pages
606 Full-Response = Status-Line
607 *( General-Header
608 | Response-Header
609 | Entity-Header )
610 CRLF
611 [ Entity-Body ]
612
613 Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
614 General-Header = Date | Pragma
615 Response-Header = Location | Server | WWW-Authenticate
616 Entity-Header = Allow | Content-Encoding | Content-Length | Content-Type
617 | Expires | Last-Modified | extension-header
618*
619***********************************************************************************************************************/
620void sendPage(EthernetClient & client, int nUriIndex, BUFFER & requestContent)
621{
622 // Read Sensor values for every page reload
623 ReadSensorM(-1,100);
624 ReadCurrentM(-1,100);
625
626#ifdef DEBUG
627 Serial.print("sendPage(");
628 Serial.print(nUriIndex); Serial.print(", ");
629 Serial.print(requestContent);
630 Serial.println(")");
631#endif
632
633 if (strncmp(requestContent, "Button1=", 8) == 0){
634 //Action1(strncmp(&requestContent[9], "true", 4) == 0);
635 MoveTo(0, _EndPoint, 255);
636 }
637 else if (strncmp(requestContent, "Button2=", 8) == 0){
638 //Action2(strncmp(&requestContent[9], "true", 4) == 0);
639 MoveTo(0, _StartPoint, 255);
640 }
641 else if (strncmp(requestContent, "Button3=", 8) == 0){
642 //Action3(strncmp(&requestContent[9], "true", 4) == 0);
643 MoveTo(1, _EndPoint, 255);
644 }
645 else if (strncmp(requestContent, "Button4=", 8) == 0){
646 //Action4(strncmp(&requestContent[9], "true", 4) == 0);
647 MoveTo(1, _StartPoint, 255);
648 }
649 else if (strncmp(requestContent, "Button5=", 8) == 0){
650 MoveTo(1, _StartPoint, 255);
651 delay(100);
652 MoveTo(0, _StartPoint, 255);
653 }
654 else if (strncmp(requestContent, "Button6=", 8) == 0){
655 MoveTo(0, _EndPoint, 255);
656 delay(100);
657 MoveTo(1, _EndPoint, 255);
658 }
659#ifdef DEBUG
660 else if (strncmp(requestContent, "", 1) == 0)
661 Serial.print("-> Refresh\n");
662 else
663 Serial.print("-> not recognized\n");
664#endif
665
666 // send HTML header
667 // sendProgMemAsString(client,(char*)pgm_read_word(&(contents_main[CONT_HEADER])));
668 sendProgMemAsString(client, (char*)pgm_read_word(&(contents_main[CONT_TOP])));
669
670 // send menu
671 sendProgMemAsString(client, (char*)pgm_read_word(&(contents_main[CONT_MENU])));
672
673 // send title
674 sendProgMemAsString(client, (char*)pgm_read_word(&(contents_titles[nUriIndex])));
675
676 // send the body for the requested page
677 sendUriContentByIndex(client, nUriIndex, requestContent);
678
679 // Append the data sent in the original HTTP request
680 client.print("<br/>");
681 // send POST variables
682 client.print(requestContent);
683
684 // send footer
685 sendProgMemAsString(client,(char*)pgm_read_word(&(contents_main[CONT_FOOTER])));
686}
687
688/**********************************************************************************************************************
689* Send Images
690***********************************************************************************************************************/
691void sendImage(EthernetClient & client, int nUriIndex, BUFFER & requestContent)
692{
693 int nImageIndex = nUriIndex - NUM_PAGES;
694
695 // send the header for the requested image
696 sendUriContentByIndex(client, nUriIndex, requestContent);
697
698 // send the image data
699 sendProgMemAsBinary(client, (char *)pgm_read_word(&(data_for_images[nImageIndex])), (int)pgm_read_word(&(size_for_images[nImageIndex])));
700}
701
702/**********************************************************************************************************************
703* Send content split by buffer size
704***********************************************************************************************************************/
705// If we provide string data then we don't need specify an explicit size and can do a string copy
706void sendProgMemAsString(EthernetClient & client, const char *realword)
707{
708 sendProgMemAsBinary(client, realword, strlen_P(realword));
709}
710
711// Non-string data needs to provide an explicit size
712void sendProgMemAsBinary(EthernetClient & client, const char* realword, int realLen)
713{
714 int remaining = realLen;
715 const char * offsetPtr = realword;
716 int nSize = sizeof(BUFFER);
717 BUFFER buffer;
718
719 while (remaining > 0)
720 {
721 // print content
722 if (nSize > remaining)
723 nSize = remaining; // Partial buffer left to send
724
725 memcpy_P(buffer, offsetPtr, nSize);
726
727 if (client.write((const uint8_t *)buffer, nSize) != nSize)
728 Serial.println("Failed to send data");
729
730 // more content to print?
731 remaining -= nSize;
732 offsetPtr += nSize;
733 }
734}
735
736/**********************************************************************************************************************
737* Send real page content
738***********************************************************************************************************************/
739// This method takes the contents page identified by nUriIndex, divides it up into buffer-sized
740// strings, passes it on for STX substitution and finally sending to the client.
741void sendUriContentByIndex(EthernetClient client, int nUriIndex, BUFFER & requestContent)
742{
743 // Locate the page data for the URI and prepare to process in buffer-sized chunks.
744 const char * offsetPtr; // Pointer to offset within URI for data to be copied to buffer and sent.
745 char *pNextString;
746 int nSubstituteIndex = -1; // Count of substitutions so far for this URI
747 int remaining; // Total bytes (of URI) remaining to be sent
748 int nSize = sizeof(BUFFER) - 1; // Effective size of buffer allowing last char as string terminator
749 BUFFER buffer;
750
751 if (nUriIndex < NUM_PAGES)
752 offsetPtr = (char*)pgm_read_word(&(contents_pages[nUriIndex]));
753 else
754 offsetPtr = (char*)pgm_read_word(&(image_header));
755
756 buffer[nSize] = 0; // ensure there is always a string terminator
757 remaining = strlen_P(offsetPtr); // Set total bytes of URI remaining
758
759 while (remaining > 0)
760 {
761 // print content
762 if (nSize > remaining)
763 {
764 // Set whole buffer to string terminator before copying remainder.
765 memset(buffer, 0, STRING_BUFFER_SIZE);
766 nSize = remaining; // Partial buffer left to send
767 }
768 memcpy_P(buffer, offsetPtr, nSize);
769 offsetPtr += nSize;
770 // We have a buffer's worth of page to check for substitution markers/delimiters.
771 // Scan the buffer for markers, dividing it up into separate strings.
772 if (buffer[0] == *pStxDelimiter) // First char is delimiter
773 {
774 sendSubstitute(client, nUriIndex, ++nSubstituteIndex, requestContent);
775 --remaining;
776 }
777 // First string is either terminated by the null at the end of the buffer
778 // or by a substitution delimiter. So simply send it to the client.
779 pNextString = strtok(buffer, pStxDelimiter);
780 client.print(pNextString);
781 remaining -= strlen(pNextString);
782 // Scan for strings between delimiters
783 for (pNextString = strtok(NULL, pStxDelimiter); pNextString != NULL && remaining > 0; pNextString = strtok(NULL, pStxDelimiter))
784 {
785 // pNextString is pointing to the next string AFTER a delimiter
786 sendSubstitute(client, nUriIndex, ++nSubstituteIndex, requestContent);
787 --remaining;
788 client.print(pNextString);
789 remaining -= strlen(pNextString);
790 }
791 }
792}
793
794// Call this method in response to finding a substitution character '\002' within some
795// URI content to send the appropriate replacement text, depending on the URI index and
796// the substitution index within the content.
797void sendSubstitute(EthernetClient client, int nUriIndex, int nSubstituteIndex, BUFFER & requestContent)
798{
799#ifdef DEBUG
800 Serial.print("sendSubstitute(");
801 Serial.print(nUriIndex); Serial.print(", ");
802 Serial.print(nSubstituteIndex); Serial.print(", ");
803 Serial.print(requestContent);
804 Serial.print(")\n");
805#endif
806 if (nUriIndex < NUM_PAGES)
807 {
808 // Page request
809 switch (nUriIndex)
810 {
811 case 1: // page 2
812#ifdef DEBUG
813 Serial.println(" -> Case 1");
814#endif
815 if (nSubstituteIndex < 4){
816 //client.print("<b>");
817 client.print(_currentValue[nSubstituteIndex/2]);
818 //client.print("</b>");
819 }
820 else if ( (nSubstituteIndex >= 4) &&
821 (nSubstituteIndex < 8) ) {
822 //client.print("<b>");
823 client.print(_sensorValue[nSubstituteIndex/2-2]);
824 //client.print("</b>");
825 }
826 else if ( (nSubstituteIndex >= 8) &&
827 (nSubstituteIndex < 12) ) {
828 //client.print("<b>");
829 client.print(_StatusLabel[_LidStatus[nSubstituteIndex/2-4]]);
830 //client.print("</b>");
831
832 }
833 break;
834 case 2: // page 3
835 Serial.println(" -> Case 2");
836//
837// switch (nSubstituteIndex)
838// {
839// case 0: // LedOn button send value
840//#ifdef DEBUG
841// Serial.println(requestContent);
842//#endif
843// if (strncmp(requestContent, "Button1=", 8) == 0)
844// Action1(strncmp(&requestContent[9], "true", 4) == 0);
845//
846// client.print(Action1 ? "false" : "true");
847// break;
848// case 1: // LedOn button legend
849// //client.print(isLedOn ? "Off" : "On");
850// break;
851// case 2: // LedOn partial image name
852// //client.print(isLedOn ? "on" : "off");
853// break;
854// default:
855// break;
856// }
857 break;
858 }
859 }
860 else
861 {
862 // Image request
863 int nImageIndex = nUriIndex - NUM_PAGES;
864
865 switch (nSubstituteIndex)
866 {
867 case 0:
868 // Content-Length value - ie. image size
869 char strSize[6]; // Up to 5 digits plus null terminator
870 itoa((int)pgm_read_word(&(size_for_images[nImageIndex])), strSize, 10);
871 //Serial.println(strSize); // Debug
872 client.print(strSize);
873 break;
874 case 1:
875 // Content-Type partial value
876 switch (nImageIndex)
877 {
878 case 0: // favicon
879 client.print("x-icon");
880 break;
881 case 1: // led on image
882 case 2: // led off image
883 client.print("png");
884 break;
885 }
886 }
887 }
888}
889#endif
890//
891//void Action1(bool argument)
892//{
893// Serial.print("Action->Action1(");
894// Serial.print(argument);
895// Serial.print(")\n");
896//
897// // Move motor 0 out
898// int m=0;
899// MoveTo(m, 1023, 200);
900//
901//}
902
903//void Action2(bool argument)
904//{
905// Serial.print("Action->Action2(");
906// Serial.print(argument);
907// Serial.print(")\n");
908//
909// // Move motor 1 out
910// int m=0;
911// MoveTo(m, 0, 200);
912//}
913//
914//void Action3(bool argument)
915//{
916// Serial.print("Action->Action3(");
917// Serial.print(argument);
918// Serial.print(")\n");
919//
920// // Move motor 0 in
921// int m=1;
922// MoveTo(m, 1023, 200);
923//}
924//
925//void Action4(bool argument)
926//{
927// Serial.print("Action->Action4(");
928// Serial.print(argument);
929// Serial.print(")\n");
930//
931// // Move motor 1 in
932// int m=1;
933// MoveTo(m, 0, 200);
934//}
935//
936// position in [%]-> [0-1] Closed-Open
937//
938void MoveTo(int motor, double target_position, int mySpeed){
939
940 // define tmp value for the speed
941 int speedTmp = 0;
942
943 // define variable containing the current actuator position
944 // the travel to be done to rech the target position and the
945 // motor current
946 double current_position;
947 double err_current_position;
948
949 double original_position;
950 double err_original_position;
951
952 double motor_current;
953 double err_motor_current;
954
955 double travel;
956
957 // only one reading to define the position is not sufficient
958 // current_position = ReadSensor(motor);
959
960 // Calculate average final position
961 double tmp=0;
962 double tmpM=0;
963 double tmpS=0;
964 int steps=0;
965
966 for (int i=0;i<SAMPLES;i++){
967 tmp=ReadSensor(motor);
968 tmpM += tmp;
969 tmpS += tmp*tmp;
970 }
971 tmpM /= SAMPLES;
972 tmpS = sqrt(tmpS/SAMPLES - tmpM*tmpM);
973
974
975 int tmpS_int = (int) tmpS;
976
977 // round the mean to it to the closest integer
978 current_position = (int) (tmpM+0.5);
979 if (((int)tmpS) < 1){
980 err_current_position = 1.;
981 }
982 else{
983 err_current_position = tmpS;
984 }
985
986 original_position = current_position;
987 err_original_position = err_current_position;
988
989 // calculate the travel needed to reach the target position
990 travel = target_position - current_position;
991
992 Serial.print("Moving motor ");
993 Serial.print(motor);
994 Serial.print(" from pos. ");
995 Serial.print(current_position,3);
996 Serial.print(" to position ");
997 Serial.print(target_position,3);
998 Serial.print(" - Travel distance = ");
999 Serial.println(travel,3);
1000
1001 Serial.print(" - The current position of the actuator is ");
1002 Serial.print(tmpM,3);
1003 Serial.print( " +/- " );
1004 Serial.println(tmpS,3);
1005
1006 Serial.print(" - The corrected position of the actuator is ");
1007 Serial.print(current_position);
1008 Serial.print( " +/- " );
1009 Serial.println(err_current_position);
1010
1011
1012 // [IF] the travel is bigger than +2*(absolute position error) try to move out the motor
1013 if (travel > 2*err_current_position){
1014 // Try to place here (if you have time) a speed self adjucting algorithm
1015 // base on the trave which the actuator has still to do
1016 if( _LidStatus[motor] != _CLOSED){
1017
1018 Serial.println(" - going out (lid closing)");
1019 speedTmp = mySpeed; // positive speed
1020 steps++;
1021 _LidStatus[motor] = _CLOSING;
1022
1023 // Accelerate motor from 0 to speedTmp linearly
1024 for (int j=0;j<speedTmp;j++){
1025 Motor(motor, j);
1026 delay(1);
1027 }
1028 }
1029 else{
1030 Serial.println(" - already closed");
1031
1032 _LidStatus[motor] = _CLOSED;
1033 return;
1034 }
1035 }
1036 // [ELSE IF] travel is between -2*(absolute position error) and +2*(absolute position error)
1037 // consider yourself already in position
1038 else if (travel <= 2*err_current_position &&
1039 travel >= -2*err_current_position ){
1040 Serial.println(" - already in place");
1041
1042 _LidStatus[motor] = _STEADY;
1043 return;
1044 // already in place don't bother moving more.
1045 }
1046 // [ELSE} if the travel is smaller than -2*(absolute position error) try to move in the motor
1047 else{
1048 Serial.println(" - going in (lid opening)");
1049 speedTmp = -mySpeed; // negative speed
1050 steps++;
1051 _LidStatus[motor] = _OPENING;
1052
1053 // Accelerate motor from 0 to -speedTmp linearly
1054 for (int j=0;j>speedTmp;j--){
1055 Motor(motor, j);
1056 delay(1);
1057 }
1058 }
1059
1060
1061 // Start the main loop which checks the motors while they are mooving
1062 tmp=0;
1063 tmpM=0;
1064 tmpS=0;
1065 for (steps=1;abs(travel) != 0 ;steps++){
1066 //Read Current
1067 motor_current = ReadCurrentM(motor,10);
1068
1069 // If Overcurrent stop
1070 if (motor_current > _OverCurrent){
1071 Motor(motor, 0); // Stop Motor
1072
1073 Serial.print(" - WARNING!!! Overcurrent ");
1074 Serial.print(motor_current,3);
1075 Serial.print(" [A] at position ");
1076 Serial.println(current_position,3);
1077
1078 _LidStatus[motor] = _OVER_CURRENT;
1079 return;
1080 }
1081
1082 // If Fault stop
1083 if (getFault(motor)){
1084 Motor(motor, 0); // Stop Motor
1085 Serial.print(" - GetFault - at position ");
1086 Serial.println(current_position,3);
1087 _LidStatus[motor] = _MOTOR_FAULT;
1088 break;
1089 }
1090
1091 // Average Current around the steps
1092 tmp = motor_current;
1093 tmpM += tmp;
1094 tmpS += tmp*tmp;
1095
1096 // Read current position
1097 // it doesn't make sense to read it here more time as the actuars are moving
1098 current_position = ReadSensorM(motor,10);
1099
1100 // Calculate travel distance
1101 travel = target_position - current_position;
1102
1103 // Read current absorbed the motor and append the values for the calculation
1104 // of the mean value and its error
1105
1106
1107 // [IF] the current drops below ~0.07 A might means that the end swirch
1108 // stopped the motor check also the position to determine if this is true.
1109 if (motor_current < _ZeroCurrent){
1110 // Closing
1111 if ( current_position > _EndPointLimit && target_position > _EndPointLimit ){
1112 Serial.print(" - Reached End of Actuator. Pos = ");
1113 Serial.println(current_position, 3);
1114
1115 _LidStatus[motor] = _CLOSED;
1116 break; //Exit from the for loop
1117 }
1118 // Opening
1119 else if (current_position < _StartPointLimit && target_position < _StartPointLimit ){
1120 Serial.print(" - Reached Beginning of Actuator. Pos = ");
1121 Serial.println(current_position, 3);
1122
1123 _LidStatus[motor] = _OPEN;
1124 break; //Exit from the for loop
1125 }
1126 // Error
1127 else {
1128 Serial.print(" - Error!! No current in motor ");
1129 Serial.print(motor);
1130 Serial.print(". I= ");
1131 Serial.print(motor_current);
1132 Serial.print("A . Pos = ");
1133 Serial.println(current_position, 3);
1134
1135 _LidStatus[motor] = _POWER_PROBLEM;
1136 break; //Exit from the for loop
1137 }
1138 }
1139
1140 if (_LidStatus[motor] == _CLOSING && motor_current > _CurrentPushingLimit && current_position > _EndPointLimit){
1141 Serial.print(" - step ");
1142 Serial.print(steps);
1143 // double travel_done= (55. * (target_position - original_position))/1024.;
1144 // Serial.print(" - travelled for ");
1145 // Serial.print(travel_done);
1146 Serial.print(" - pushing -> I = ");
1147 Serial.print(motor_current, 3);
1148 Serial.println(" A");
1149 _LidStatus[motor] = _CLOSED;
1150 break;
1151 }
1152
1153 // If too many cycles of the loop print a message and check the position and the current
1154 if (steps %50 == 0){
1155 Serial.print(" - step ");
1156 Serial.print(steps);
1157 Serial.print(" - still in loop. Pos = ");
1158 Serial.print(current_position, 3);
1159 Serial.print(" - Istantaneous current = ");
1160 Serial.print(motor_current, 3);
1161 Serial.print(" A");
1162 Serial.print(" - Average current = ");
1163 Serial.print(tmpM/steps, 3);
1164 Serial.println(" A");
1165
1166
1167 if( _LidStatus[motor] != _CLOSING &&
1168 _LidStatus[motor] != _OPENING)
1169 _LidStatus[motor] = _MOVING;
1170
1171 // Redefine better those limits... they might not be necessary with the new low
1172 // current limits
1173 //if (steps %500 && current_position > 1000 && target_position > 1000 ){
1174 // Serial.print(" - Reached End of Actuator. Pos = ");
1175 // Serial.println(current_position, 3);
1176 // break;
1177 //}
1178 //if (steps %500 && current_position < 80 && target_position < 80 ){
1179 // Serial.print(" - Reached Beginning of Actuator. Pos = ");
1180 // Serial.println(current_position, 3);
1181 // break;
1182 //}
1183 }
1184
1185
1186
1187 // minimum delay between a cycle and the other is 1 ms
1188 delay (10);
1189 }
1190
1191 // At this stage the motor should be stopped in any case
1192 Motor(motor, 0);
1193 Serial.print(" - motor reached the destination - pos. ");
1194 Serial.println(current_position,3);
1195
1196 // Calculate current average and sigma
1197 tmpM /= steps;
1198 tmpS = sqrt(tmpS/steps - tmpM*tmpM);
1199 Serial.print(" - average current over the loop ");
1200 Serial.print(tmpM,3);
1201 Serial.print( " +/- " );
1202 Serial.println(tmpS,3);
1203
1204 // Wait 100 ms then calculate average final position
1205 delay(100);
1206 tmp=0; tmpM=0; tmpS=0;
1207
1208 for (int i=0;i<SAMPLES;i++){
1209 tmp=ReadSensor(motor);
1210 tmpM += tmp;
1211 tmpS += tmp*tmp;
1212 }
1213 tmpM /= SAMPLES;
1214 tmpS = sqrt(tmpS/SAMPLES - tmpM*tmpM);
1215
1216 Serial.print(" - final position is ");
1217 Serial.print(tmpM,3);
1218 Serial.print( " +/- " );
1219 Serial.println(tmpS,3);
1220
1221 Serial.print(" - Lid staus is ");
1222 Serial.println(_StatusLabel[_LidStatus[motor]]);
1223
1224 Serial.print("AvailableMemory()=");
1225 Serial.println(availableMemory());
1226
1227
1228}
1229
1230int availableMemory() {
1231 int free_memory;
1232 if ((int)__brkval==0)
1233 free_memory = ((int)&free_memory) - ((int) &__bss_end);
1234 else
1235 free_memory = ((int)&free_memory) - ((int) &__brkval);
1236
1237 return free_memory;
1238}
1239
1240
1241// ReadSensor(-1); - Read all sensor
1242// ReadSensor(0); - Read sensor 0
1243// ReadSensor(1); - Read sensor 1
1244double ReadSensor(int motor){
1245#ifdef DEBUG
1246 Serial.println("Action->ReadSensors()");
1247#endif
1248
1249 switch (motor){
1250 case -1: // Read all of them
1251 _sensorValue[0] = analogRead(A2);//*_ADC2V - _Voffset;// *_Compensation; // Actuator 1 position
1252 _sensorValue[1] = analogRead(A3);//*_ADC2V - _Voffset;// *_Compensation; // Actuator 2 position
1253 return -1;
1254 case 0:
1255 _sensorValue[motor] = analogRead(A2);//*_ADC2V - _Voffset; //*_Compensation;
1256 return _sensorValue[motor]; // Actuator 1 position
1257 case 1:
1258 _sensorValue[motor] = analogRead(A3);//*_ADC2V - _Voffset;//_Compensation;
1259 return _sensorValue[motor]; // Actuator 1 position
1260 }
1261}
1262
1263double ReadSensorM(int motor, int samples){
1264#ifdef DEBUG
1265 Serial.println("Action->ReadSensorsM()");
1266#endif
1267 switch (motor){
1268 case -1: // Read all of them
1269 _sensorValue[0] = 0;
1270 _sensorValue[1] = 0;
1271 for (int j=0;j<samples;j++){
1272 _sensorValue[0] += analogRead(A2);
1273 _sensorValue[1] += analogRead(A3);
1274 }
1275 _sensorValue[0]/=samples;
1276 _sensorValue[1]/=samples;
1277 return -1;
1278
1279 case 0:
1280 _sensorValue[motor]=0;
1281 for (int j=0;j<samples;j++)
1282 _sensorValue[motor] += analogRead(A2);//*_ADC2V - _Voffset; //*_Compensation;
1283 _sensorValue[motor] /= samples;
1284 return _sensorValue[motor]; // Actuator 1 position
1285
1286 case 1:
1287 _sensorValue[motor]=0;
1288 for (int j=0;j<samples;j++)
1289 _sensorValue[motor] += analogRead(A3);//*_ADC2V - _Voffset;//_Compensation;
1290 _sensorValue[motor] /= samples;
1291 return _sensorValue[motor]; // Actuator 1 position
1292 }
1293
1294}
1295
1296
1297// ReadCurrent(-1); - Read current for all the motors
1298// ReadCurrent(0); - Read motor 0 current
1299// ReadCurrent(1); - Read motor 1 current
1300double ReadCurrent(int motor){
1301 switch (motor){
1302 case -1: // Read all of them
1303 _currentValue[0] = analogRead(A4)*_ADC2V/(_V2A*10.);
1304 _currentValue[1] = analogRead(A5)*_ADC2V/(_V2A*10.);
1305 Serial.println("Action->ReadSensors()");
1306 return -1;
1307 case 0:
1308 _currentValue[motor] = analogRead(A4)*_ADC2V/(_V2A*10.);
1309 return _currentValue[motor]; // Current of the motor
1310 case 1:
1311 _currentValue[motor] = analogRead(A5)*_ADC2V/(_V2A*10.);
1312 return _currentValue[motor]; // Current of the motor
1313 }
1314}
1315
1316double ReadCurrentM(int motor, int samples){
1317 switch (motor){
1318 case -1: // Read all of them
1319 _currentValue[0] = 0;
1320 _currentValue[1] = 0;
1321 for (int j=0;j<samples;j++){
1322 _currentValue[0] += analogRead(A4)*_ADC2V/(_V2A*10.);
1323 _currentValue[1] += analogRead(A5)*_ADC2V/(_V2A*10.);
1324 }
1325 _currentValue[0]/=samples;
1326 _currentValue[1]/=samples;
1327 return -1;
1328 case 0:
1329 _currentValue[motor] = 0;
1330 for (int j=0;j<samples;j++)
1331 _currentValue[motor] += analogRead(A4)*_ADC2V/(_V2A*10.);
1332 _currentValue[motor]/=samples;
1333 return _currentValue[motor];
1334 case 1:
1335 _currentValue[motor] = 0;
1336 for (int j=0;j<samples;j++)
1337 _currentValue[motor] += analogRead(A5)*_ADC2V/(_V2A*10.);
1338 _currentValue[motor]/=samples;
1339 return _currentValue[motor];
1340
1341 }
1342
1343}
1344
1345
1346// Return error status for motor
1347unsigned char getFault(int motor)
1348{
1349 return 0; //!digitalRead(_ENDIAG[motor]);
1350}
1351
1352// control motor, -255 < pwm < 255
1353//
1354void Motor(int motor, int pwm){
1355 bool reverse = false;
1356
1357 // Check sign and direction
1358 if (pwm < 0){
1359 pwm = -pwm;
1360 reverse = true;
1361 }
1362
1363 // Check max speed
1364 if (pwm > 255) pwm = 255;
1365 else if (pwm < -255) pwm = -255;
1366
1367 // Activate motors
1368 analogWrite(_pinPWM[motor], pwm); //set pwm control, 0 for stop, and 255 for maximum speed
1369 if (pwm != 0){
1370 if(reverse) {
1371 digitalWrite(_pinDA[motor], HIGH);
1372 digitalWrite(_pinDB[motor], LOW);
1373 }
1374 else {
1375 digitalWrite(_pinDA[motor], LOW);
1376 digitalWrite(_pinDB[motor], HIGH);
1377 }
1378 }
1379 else {
1380 digitalWrite(_pinDA[motor], LOW);
1381 digitalWrite(_pinDB[motor], LOW);
1382 }
1383}
1384
1385
Note: See TracBrowser for help on using the repository browser.