Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 306 lines (252 sloc) 7.809 kb
ecdbe44 @lazyatom Initial commit.
lazyatom authored
1 #include <SPI.h>
2 #include <Ethernet.h>
3 #include <SD.h>
644a356 @lazyatom Randomly generate an ID on first boot.
lazyatom authored
4 #include <EEPROM.h>
ecdbe44 @lazyatom Initial commit.
lazyatom authored
5
6 #include <SoftwareSerial.h>
001cc6f @lazyatom Use latest version of Bounce Arduino library.
lazyatom authored
7 #include <Bounce2.h>
ecdbe44 @lazyatom Initial commit.
lazyatom authored
8
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
9 // -- Settings for YOU to change if you want
29e57ce @lazyatom Pull all the settings variables up to the top.
lazyatom authored
10
afa2f60 @lazyatom Use a more generic fake MAC.
lazyatom authored
11 byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // physical mac address
db1dfb3 @lazyatom Printers have IDs.
lazyatom authored
12
953403c @lazyatom Add more context about the type parameters near where it is set.
lazyatom authored
13 // The printerType controls the format of the data sent from the server
14 // If you're using a completely different kind of printer, change this
15 // to correspond to your printer's PrintProcessor implementation in the
16 // server.
17 //
18 // If you want to control the darkness of your printouts, append a dot and
19 // a number, e.g. A2-raw.240 (up to a maximum of 255).
20 //
21 // If you want to flip the vertical orientation of your printouts, append
22 // a number and then .flipped, e.g. A2-raw.240.flipped
5d245cc @chrisroos Use an array of type char rather than pointers.
chrisroos authored
23 const char printerType[] = "A2-raw";
29acb57 @lazyatom Remove debug IP addresses.
lazyatom authored
24
857ac81 @lazyatom Migrate the project to Exciting owner.
lazyatom authored
25 const char host[] = "printer.exciting.io"; // the host of the backend server
29e57ce @lazyatom Pull all the settings variables up to the top.
lazyatom authored
26 const unsigned int port = 80;
ecfcb90 @lazyatom Switch to using a raw print format.
lazyatom authored
27
4c43249 @lazyatom The polling delay is a constant.
lazyatom authored
28 const unsigned long pollingDelay = 10000; // delay between polling requests (milliseconds)
29e57ce @lazyatom Pull all the settings variables up to the top.
lazyatom authored
29
f604e87 @lazyatom Pin rearrangement.
lazyatom authored
30 const byte printer_TX_Pin = 9; // this is the yellow wire
31 const byte printer_RX_Pin = 8; // this is the green wire
32 const byte errorLED = 7; // the red LED
29e57ce @lazyatom Pull all the settings variables up to the top.
lazyatom authored
33 const byte downloadLED = 6; // the amber LED
f604e87 @lazyatom Pin rearrangement.
lazyatom authored
34 const byte readyLED = 5; // the green LED
35 const byte buttonPin = 3; // the print button
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
36 const byte SD_Pin = 4; // the SD Card SPI pin
29e57ce @lazyatom Pull all the settings variables up to the top.
lazyatom authored
37
b4d812b @chrisroos Disable debug by default
chrisroos authored
38 // #define DEBUG // When debug is enabled, log a bunch of stuff to the hardware Serial
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
39
40 // -- Everything below here can be left alone
41
001cc6f @lazyatom Use latest version of Bounce Arduino library.
lazyatom authored
42 const char sketchVersion[] = "1.0.6";
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
43
44 // -- Debugging
29e57ce @lazyatom Pull all the settings variables up to the top.
lazyatom authored
45
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
46 #ifdef DEBUG
a4543f2 @lazyatom Reduce sketch size from to 29210 to 28934.
lazyatom authored
47 void debugTimeAndSeparator() {
48 Serial.print(millis()); Serial.print(": ");
49 }
2a7f57b @chrisroos Avoid compiler warning in debug method signature.
chrisroos authored
50 void debug(const char *a) {
a4543f2 @lazyatom Reduce sketch size from to 29210 to 28934.
lazyatom authored
51 debugTimeAndSeparator(); Serial.println(a);
bcd558f @lazyatom Reduce sketch size from 31138 to 29210 bytes.
lazyatom authored
52 }
a4543f2 @lazyatom Reduce sketch size from to 29210 to 28934.
lazyatom authored
53 #define debug2(a, b) debugTimeAndSeparator(); Serial.print(a); Serial.println(b);
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
54 #else
55 #define debug(a)
56 #define debug2(a, b)
57 #endif
ecdbe44 @lazyatom Initial commit.
lazyatom authored
58
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
59
60 // -- Initialize the printer ID
61
644a356 @lazyatom Randomly generate an ID on first boot.
lazyatom authored
62 const byte idAddress = 0;
63 char printerId[17]; // the unique ID for this printer.
64
4bed04a @chrisroos Rename initSettings.
chrisroos authored
65 inline void initPrinterID() {
27c2c41 @chrisroos-and-lazyatom Improve reliability of first-boot ID generation.
chrisroos-and-lazyatom authored
66 if ((EEPROM.read(idAddress) == 255) || (EEPROM.read(idAddress+1) == 255)) {
682f15c @lazyatom Shorter strings == smaller sketch.
lazyatom authored
67 debug("Generating new ID");
644a356 @lazyatom Randomly generate an ID on first boot.
lazyatom authored
68 randomSeed(analogRead(0) * analogRead(5));
69 for(int i = 0; i < 16; i += 2) {
6a5ce26 @lazyatom Add more debug to ID generation.
lazyatom authored
70 printerId[i] = random(48, 57); // 0-9
71 printerId[i+1] = random(97, 122); // a-z
644a356 @lazyatom Randomly generate an ID on first boot.
lazyatom authored
72 EEPROM.write(idAddress + i, printerId[i]);
73 EEPROM.write(idAddress + i+1, printerId[i+1]);
74 }
75 } else {
76 for(int i = 0; i < 16; i++) {
77 printerId[i] = (char)EEPROM.read(idAddress + i);
78 }
79 }
80 printerId[16] = '\0';
682f15c @lazyatom Shorter strings == smaller sketch.
lazyatom authored
81 debug2("ID: ", printerId);
644a356 @lazyatom Randomly generate an ID on first boot.
lazyatom authored
82 }
83
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
84
85 // -- Initialize the LEDs
86
ba52259 @lazyatom Save about 2 bytes per function by making them inline.
lazyatom authored
87 inline void initDiagnosticLEDs() {
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
88 pinMode(errorLED, OUTPUT);
89 pinMode(downloadLED, OUTPUT);
90 pinMode(readyLED, OUTPUT);
91 digitalWrite(errorLED, HIGH);
92 digitalWrite(downloadLED, HIGH);
93 digitalWrite(readyLED, HIGH);
94 delay(1000);
95 digitalWrite(errorLED, LOW);
96 digitalWrite(downloadLED, LOW);
97 digitalWrite(readyLED, LOW);
1098c71 @lazyatom Move the delay which clarifies error flashing to a clearer place.
lazyatom authored
98 delay(500);
a513495 @lazyatom Encapsulate the LEDs in a function.
lazyatom authored
99 }
ecdbe44 @lazyatom Initial commit.
lazyatom authored
100
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
101 // -- Initialize the printer connection
102
ecfcb90 @lazyatom Switch to using a raw print format.
lazyatom authored
103 SoftwareSerial *printer;
104 #define PRINTER_WRITE(b) printer->write(b)
ecdbe44 @lazyatom Initial commit.
lazyatom authored
105
ba52259 @lazyatom Save about 2 bytes per function by making them inline.
lazyatom authored
106 inline void initPrinter() {
ecfcb90 @lazyatom Switch to using a raw print format.
lazyatom authored
107 printer = new SoftwareSerial(printer_RX_Pin, printer_TX_Pin);
108 printer->begin(19200);
ecdbe44 @lazyatom Initial commit.
lazyatom authored
109 }
110
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
111
112 // -- Initialize the SD card
113
ba52259 @lazyatom Save about 2 bytes per function by making them inline.
lazyatom authored
114 inline void initSD() {
ecdbe44 @lazyatom Initial commit.
lazyatom authored
115 pinMode(SD_Pin, OUTPUT);
d7e26e0 @chrisroos Abort if there are problems with the SD Card.
chrisroos authored
116 if (!SD.begin(SD_Pin)) {
117 // SD Card failure.
118 terminalError(2);
119 }
ecdbe44 @lazyatom Initial commit.
lazyatom authored
120 }
121
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
122
123 // -- Initialize the Ethernet connection & DHCP
124
db5628a @lazyatom Keep the global variables with their respective setup functions.
lazyatom authored
125 EthernetClient client;
ba52259 @lazyatom Save about 2 bytes per function by making them inline.
lazyatom authored
126 inline void initNetwork() {
ecdbe44 @lazyatom Initial commit.
lazyatom authored
127 // start the Ethernet connection:
128 if (Ethernet.begin(mac) == 0) {
4e89aaa @chrisroos Remove some unnecessary debug statements.
chrisroos authored
129 // DHCP Failure
d7e26e0 @chrisroos Abort if there are problems with the SD Card.
chrisroos authored
130 terminalError(3);
ecdbe44 @lazyatom Initial commit.
lazyatom authored
131 }
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
132 delay(1000);
ecdbe44 @lazyatom Initial commit.
lazyatom authored
133 // print your local IP address:
682f15c @lazyatom Shorter strings == smaller sketch.
lazyatom authored
134 debug2("IP: ", Ethernet.localIP());
ecdbe44 @lazyatom Initial commit.
lazyatom authored
135 }
136
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
137
001cc6f @lazyatom Use latest version of Bounce Arduino library.
lazyatom authored
138 // -- Initialize debouncing of buttons
139
140 Bounce bouncer = Bounce();
141
142 void initBouncer() {
143 bouncer.attach(buttonPin);
144 bouncer.interval(5);
145 }
146
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
147 // -- Setup; runs once on boot.
148
ecdbe44 @lazyatom Initial commit.
lazyatom authored
149 void setup(){
ecfcb90 @lazyatom Switch to using a raw print format.
lazyatom authored
150 #ifdef DEBUG
ecdbe44 @lazyatom Initial commit.
lazyatom authored
151 Serial.begin(9600);
ecfcb90 @lazyatom Switch to using a raw print format.
lazyatom authored
152 #endif
edc1ab9 @chrisroos Initialise the LEDs before anything else.
chrisroos authored
153 initDiagnosticLEDs();
4bed04a @chrisroos Rename initSettings.
chrisroos authored
154 initPrinterID();
ecdbe44 @lazyatom Initial commit.
lazyatom authored
155 initSD();
156 initNetwork();
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
157 initPrinter();
001cc6f @lazyatom Use latest version of Bounce Arduino library.
lazyatom authored
158 initBouncer();
ecdbe44 @lazyatom Initial commit.
lazyatom authored
159 }
160
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
161 // -- Check for new data and download if found
162
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
163 boolean downloadWaiting = false;
18db7a9 @chrisroos Avoid compiler warning in filename declaration.
chrisroos authored
164 char cacheFilename[] = "TMP";
ecfcb90 @lazyatom Switch to using a raw print format.
lazyatom authored
165 unsigned long content_length = 0;
058e2c0 @lazyatom Don't print if the status code wasn't 200.
lazyatom authored
166 boolean statusOk = false;
ecdbe44 @lazyatom Initial commit.
lazyatom authored
167
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
168 void checkForDownload() {
a749c6b @lazyatom We don't need 2-bytes for a pin number.
lazyatom authored
169 unsigned long length = 0;
ecfcb90 @lazyatom Switch to using a raw print format.
lazyatom authored
170 content_length = 0;
058e2c0 @lazyatom Don't print if the status code wasn't 200.
lazyatom authored
171 statusOk = false;
8b42d7c @lazyatom Minor sketch tweaks.
lazyatom authored
172
173 #ifdef DEBUG
154af24 @chrisroos Fix problem with crazy large durations..
chrisroos authored
174 unsigned long start = millis();
8b42d7c @lazyatom Minor sketch tweaks.
lazyatom authored
175 #endif
176
aeea4fb @lazyatom More debugging around clearing the cache.
lazyatom authored
177 if (SD.exists(cacheFilename)) {
4e89aaa @chrisroos Remove some unnecessary debug statements.
chrisroos authored
178 if (!SD.remove(cacheFilename)) {
179 // Failed to clear cache.
d7e26e0 @chrisroos Abort if there are problems with the SD Card.
chrisroos authored
180 terminalError(4);
aeea4fb @lazyatom More debugging around clearing the cache.
lazyatom authored
181 }
182 }
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
183 File cache = SD.open(cacheFilename, FILE_WRITE);
ecdbe44 @lazyatom Initial commit.
lazyatom authored
184
de582b3 @lazyatom Actually, unicorn was complaining about malformed requests.
lazyatom authored
185 debug2("Attempting to connect to ", host);
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
186 if (client.connect(host, port)) {
187 digitalWrite(downloadLED, HIGH);
db1dfb3 @lazyatom Printers have IDs.
lazyatom authored
188 client.print("GET "); client.print("/printer/"); client.print(printerId); client.println(" HTTP/1.0");
de582b3 @lazyatom Actually, unicorn was complaining about malformed requests.
lazyatom authored
189 client.print("Host: "); client.print(host); client.print(":"); client.println(port);
e348d54 @lazyatom Flushing the buffer seems to avoid the issue! Huzzah!
lazyatom authored
190 client.flush();
857ac81 @lazyatom Migrate the project to Exciting owner.
lazyatom authored
191 client.print("Accept: application/vnd.exciting.printer."); client.println(printerType);
e348d54 @lazyatom Flushing the buffer seems to avoid the issue! Huzzah!
lazyatom authored
192 client.print("X-Printer-Version: "); client.println(sketchVersion);
de582b3 @lazyatom Actually, unicorn was complaining about malformed requests.
lazyatom authored
193 client.println();
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
194 boolean parsingHeader = true;
8b42d7c @lazyatom Minor sketch tweaks.
lazyatom authored
195
ecdbe44 @lazyatom Initial commit.
lazyatom authored
196 while(client.connected()) {
197 while(client.available()) {
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
198 if (parsingHeader) {
56ed954 @chrisroos Avoid compiler warnings in our use of Stream.find.
chrisroos authored
199 client.find((char*)"HTTP/1.1 ");
06f5a2d @chrisroos Avoid compiler warning in status code declaration.
chrisroos authored
200 char statusCode[] = "xxx";
058e2c0 @lazyatom Don't print if the status code wasn't 200.
lazyatom authored
201 client.readBytes(statusCode, 3);
202 statusOk = (strcmp(statusCode, "200") == 0);
56ed954 @chrisroos Avoid compiler warnings in our use of Stream.find.
chrisroos authored
203 client.find((char*)"Content-Length: ");
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
204 char c;
205 while (isdigit(c = client.read())) {
206 content_length = content_length*10 + (c - '0');
207 }
682f15c @lazyatom Shorter strings == smaller sketch.
lazyatom authored
208 debug2("Content length: ", content_length);
56ed954 @chrisroos Avoid compiler warnings in our use of Stream.find.
chrisroos authored
209 client.find((char*)"\n\r\n"); // the first \r may already have been read above
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
210 parsingHeader = false;
211 } else {
212 cache.write(client.read());
213 length++;
214 }
ecdbe44 @lazyatom Initial commit.
lazyatom authored
215 }
682f15c @lazyatom Shorter strings == smaller sketch.
lazyatom authored
216 debug("Waiting for data");
ecdbe44 @lazyatom Initial commit.
lazyatom authored
217 }
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
218
682f15c @lazyatom Shorter strings == smaller sketch.
lazyatom authored
219 debug("Server disconnected");
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
220 digitalWrite(downloadLED, LOW);
221 // Close the connection, and flush any unwritten bytes to the cache.
ecdbe44 @lazyatom Initial commit.
lazyatom authored
222 client.stop();
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
223 cache.seek(0);
a86f30e @lazyatom Improve robustness of status code checking.
lazyatom authored
224
225 if (statusOk) {
226 if ((content_length == length) && (content_length == cache.size())) {
227 if (content_length > 0) {
228 downloadWaiting = true;
229 digitalWrite(readyLED, HIGH);
230 }
8b42d7c @lazyatom Minor sketch tweaks.
lazyatom authored
231 }
232 #ifdef DEBUG
233 else {
682f15c @lazyatom Shorter strings == smaller sketch.
lazyatom authored
234 debug2("Failure, content length: ", content_length);
235 if (content_length != length) debug2("length: ", length);
236 if (content_length != cache.size()) debug2("cache: ", cache.size());
3ed98ee @chrisroos Fail fast if we can't clear the cache.
chrisroos authored
237 digitalWrite(errorLED, HIGH);
aeea4fb @lazyatom More debugging around clearing the cache.
lazyatom authored
238 }
8b42d7c @lazyatom Minor sketch tweaks.
lazyatom authored
239 #endif
a86f30e @lazyatom Improve robustness of status code checking.
lazyatom authored
240 } else {
8b42d7c @lazyatom Minor sketch tweaks.
lazyatom authored
241 debug("Response code != 200");
a86f30e @lazyatom Improve robustness of status code checking.
lazyatom authored
242 recoverableError();
aeea4fb @lazyatom More debugging around clearing the cache.
lazyatom authored
243 }
a86f30e @lazyatom Improve robustness of status code checking.
lazyatom authored
244 } else {
245 debug("Couldn't connect");
246 recoverableError();
247 }
248
249 cache.close();
ecdbe44 @lazyatom Initial commit.
lazyatom authored
250
34c0ae9 @lazyatom We don't need the duration if DEBUG is not set.
lazyatom authored
251 #ifdef DEBUG
8b42d7c @lazyatom Minor sketch tweaks.
lazyatom authored
252 unsigned long duration = millis() - start;
682f15c @lazyatom Shorter strings == smaller sketch.
lazyatom authored
253 debug2("Bytes: ", length);
8b42d7c @lazyatom Minor sketch tweaks.
lazyatom authored
254 debug2("Duration: ", duration);
34c0ae9 @lazyatom We don't need the duration if DEBUG is not set.
lazyatom authored
255 #endif
a86f30e @lazyatom Improve robustness of status code checking.
lazyatom authored
256 }
ecdbe44 @lazyatom Initial commit.
lazyatom authored
257
c22b881 @chrisroos DRY up the flashing of error LEDs
chrisroos authored
258 void flashErrorLEDs(unsigned int times, unsigned int pause) {
3e0bade @lazyatom Save 14 bytes by avoiding a for loop.
lazyatom authored
259 while (times--) {
c22b881 @chrisroos DRY up the flashing of error LEDs
chrisroos authored
260 digitalWrite(errorLED, HIGH); delay(pause);
261 digitalWrite(errorLED, LOW); delay(pause);
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
262 }
263 }
ecdbe44 @lazyatom Initial commit.
lazyatom authored
264
c22b881 @chrisroos DRY up the flashing of error LEDs
chrisroos authored
265 inline void recoverableError() {
266 flashErrorLEDs(5, 100);
267 }
268
94a5f3b @chrisroos Allow us to pass an 'error code' to terminalError.
chrisroos authored
269 inline void terminalError(unsigned int times) {
270 flashErrorLEDs(times, 500);
727c78f @lazyatom Rename error function for consistency.
lazyatom authored
271 digitalWrite(errorLED, HIGH);
700e529 @chrisroos Explain the purpose of the infinite loop.
chrisroos authored
272 // no point in carrying on, so do nothing forevermore:
c1aaf90 @chrisroos Don't return from terminalError
chrisroos authored
273 while(true);
727c78f @lazyatom Rename error function for consistency.
lazyatom authored
274 }
275
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
276 // -- Print send any data from the cache to the printer
277
ba52259 @lazyatom Save about 2 bytes per function by making them inline.
lazyatom authored
278 inline void printFromDownload() {
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
279 File cache = SD.open(cacheFilename);
ecfcb90 @lazyatom Switch to using a raw print format.
lazyatom authored
280 byte b;
281 while (content_length--) {
282 b = (byte)cache.read();
283 PRINTER_WRITE(b);
284 }
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
285 cache.close();
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
286 downloadWaiting = false;
287 digitalWrite(readyLED, LOW);
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
288 }
ecdbe44 @lazyatom Initial commit.
lazyatom authored
289
c5c2074 @lazyatom Add a shedload of commenting.
lazyatom authored
290
291 // -- Check for new data, print if the button is pressed.
292
16516cd @lazyatom More robust version of Arduino sketch.
lazyatom authored
293 void loop() {
c1aaf90 @chrisroos Don't return from terminalError
chrisroos authored
294 if (downloadWaiting) {
295 bouncer.update();
296 if (bouncer.read() == HIGH) {
297 printFromDownload();
298 }
299 } else {
300 checkForDownload();
301 if (!downloadWaiting) {
302 delay(pollingDelay);
a86f30e @lazyatom Improve robustness of status code checking.
lazyatom authored
303 }
ecdbe44 @lazyatom Initial commit.
lazyatom authored
304 }
ecfcb90 @lazyatom Switch to using a raw print format.
lazyatom authored
305 }
Something went wrong with that request. Please try again.