source: firmware/ShutterController/ShutterController.ino@ 14272

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