-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArduinoBLE_ScanForAddress_withAdafruitGFX.ino
303 lines (274 loc) · 11.7 KB
/
ArduinoBLE_ScanForAddress_withAdafruitGFX.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/*
Here is a resource to find,view and download TrueType fonts......
https://fonts.google.com/
Here is a great resource to convert the .ttf files to a usable header file
so you can define your own custom fonts and add them to your sketch.......
https://rop.nl/truetype2gfx/
Think of the GFXcanvas1 as a blank sheet of paper that you can write to.
The blank image is defined by canvasWidth x canvasHeight (in pixles).
You can write custom text, shapes, lines, etc as found in the Adafruit GFX library.
Once you are finised drawing to the blank image, you run the PrintDefinedCanvas function.
All of your graphics and text will print out as one image.
We've printed images as large as 360x1000 but your mileage may vary.*/
#include <ArduinoBLE.h>
#include <Adafruit_GFX.h>
#include <gfxfont.h>
#include "PermanentMarker_Regular20pt7b.h"
// canvasWidth & canvasHeight can be dynmically changed in code using setCanvasSize()
int canvasWidth = 360; // Must be divisible by 8
int canvasHeight = 100; // Adjustable height
//GFXcanvas1 gfx(canvasWidth, canvasHeight); // Create a 1-bit canvas
GFXcanvas1 *gfx = nullptr;
uint8_t *imageData = nullptr; // Pointer for dynamically allocated image buffer
/* The following arrays define printer mode functions.
These command shortcuts do not work with custom test used in GFX commands.
You can build your own for other printer functions if desired.
Refer to esc/pos documentation below to learn more....
https://download4.epson.biz/sec_pubs/pos/reference_en/escpos/index.html
*/
const uint8_t TP_RESET[2] = { 0x1B, 0x40 };
const uint8_t NL[1] = { 0x0a }; // Newline
const uint8_t TP_LEFT[3] = { 0x1B, 0x61, 0 };
const uint8_t TP_CENTER[3] = { 0x1B, 0x61, 1 };
const uint8_t TP_RIGHT[3] = { 0x1B, 0x61, 2 };
const uint8_t TP_INVON[3] = { 0x1D, 0x42, 1 };
const uint8_t TP_INVOFF[3] = { 0x1D, 0x42, 0 };
const uint8_t TP_FONT1[3] = { 0x1B, 0x21, 0 };
const uint8_t TP_FONT2[3] = { 0x1B, 0x21, 1 };
const uint8_t TP_SHSW[3] = { 0x1B, 0x21, 0b00000000 };
const uint8_t TP_DHSW[3] = { 0x1B, 0x21, 0b00010000 };
const uint8_t TP_SHDW[3] = { 0x1B, 0x21, 0b00100000 };
const uint8_t TP_DHDW[3] = { 0x1B, 0x21, 0b00110000 };
const uint8_t TP_SHSW_B[3] = { 0x1B, 0x21, 0b00001000 };
const uint8_t TP_DHSW_B[3] = { 0x1B, 0x21, 0b00011000 };
const uint8_t TP_SHDW_B[3] = { 0x1B, 0x21, 0b00101000 };
const uint8_t TP_DHDW_B[3] = { 0x1B, 0x21, 0b00111000 };
const uint8_t TP_SHSW_U[3] = { 0x1B, 0x21, 0b10000000 };
const uint8_t TP_DHSW_U[3] = { 0x1B, 0x21, 0b10010000 };
const uint8_t TP_SHDW_U[3] = { 0x1B, 0x21, 0b10100000 };
const uint8_t TP_DHDW_U[3] = { 0x1B, 0x21, 0b10110000 };
const uint8_t TP_SHSW_BU[3] = { 0x1B, 0x21, 0b10001000 };
const uint8_t TP_DHSW_BU[3] = { 0x1B, 0x21, 0b10011000 };
const uint8_t TP_SHDW_BU[3] = { 0x1B, 0x21, 0b10101000 };
const uint8_t TP_DHDW_BU[3] = { 0x1B, 0x21, 0b10111000 };
const uint8_t TP_BOLD_OFF[3] = { 0x1B, 0x45, 0 };
const uint8_t TP_BOLD_ON[3] = { 0x1B, 0x45, 1 };
const uint8_t TP_NO_UNDERLINE[3] = { 0x1B, 0x2D, 0 };
const uint8_t TP_UNDERLINE[3] = { 0x1B, 0x2D, 1 };
const uint8_t TP_BOLD_UNDERLINE[3] = { 0x1B, 0x2D, 2 };
const uint8_t TP_FONT_A[3] = { 0x1B, 0x4D, 0 }; /// NORMAL SIZE
const uint8_t TP_FONT_B[3] = { 0x1B, 0x4D, 1 }; // 1/2 SIZE
bool validprinter = false;
BLEDevice peripheral;
BLEService TPserv("18f0"); ///// UUID must match your printers UUID's
BLECharacteristic TPChar("2af1", BLEWrite, BLEWriteWithoutResponse, "150"); ///// UUID must match your printers UUID's
String myPrinterAddress = "86:67:7a:b3:d9:38"; ///// Replace "86:67:7a:b3:d9:38" with your printer MAC address
void setup(void) {
Serial.begin(115200);
while (!Serial)
;
BLE.begin();
BLE.setEventHandler(BLEDiscovered, blePeripheralDiscoverHandler);
BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
BLEDevice peripheral = BLE.available();
BLE.scanForAddress(myPrinterAddress, true); ///// starts looking for your printer address
}
void loop() {
if (validprinter) {
Serial.println("PRINTING..............\n\n");
TPChar.writeValue(TP_CENTER, 3); // Sets Justify Center to justify canvas, not canvas contents
setCanvasSize(360, 600); // Dynamically set canvas size
clearCanvas(); // Clear and allocate the buffer
gfx->fillRect(0, 0, canvasWidth, canvasHeight, 1);
gfx->fillRoundRect(10, 10, canvasWidth - 20, canvasHeight - 20, 15, 0); //creates 10pix wide border box
for (int i = 0; i <= 5; i++) {
gfx->fillCircle(random(canvasWidth), random(canvasHeight), 5 * i, 1); // x, y, r, color
}
for (int i = 0; i <= 5; i++) {
gfx->drawCircle(random(canvasWidth), random(canvasHeight), 5 * i, 1); // x, y, r, color
}
for (int i = 0; i <= 5; i++) {
gfx->fillRect(random(canvasWidth), random(canvasHeight), 50, 50, 1); // xpos, ypos, x_width, y_height, color
}
for (int i = 0; i <= 5; i++) {
gfx->drawRect(random(canvasWidth), random(canvasHeight), 50, 50, 1); // xpos, ypos, x_width, y_height, color
}
for (int i = 0; i <= 5; i++) {
gfx->fillRoundRect(random(canvasWidth), random(canvasHeight), 50, 100, 20, 1); // xpos, ypos, x_width, y_height, radius, color
}
for (int i = 0; i <= 5; i++) {
gfx->drawRoundRect(random(canvasWidth), random(canvasHeight), 50, 100, 20, 1); // xpos, ypos, x_width, y_height, radius, color
}
for (int i = 0; i <= 5; i++) {
int x0 = random(canvasWidth);
int y0 = random(canvasHeight);
gfx->drawTriangle(x0, y0, x0 + 25, y0 - 50, x0 + 50, y0, 1); // x0, y0, x1, y1, x2, y2, color
}
for (int i = 0; i <= 5; i++) {
int x0 = random(canvasWidth);
int y0 = random(canvasHeight);
gfx->fillTriangle(x0, y0, x0 + 25, y0 - 50, x0 + 50, y0, 1); // x0, y0, x1, y1, x2, y2, color
}
for (int i = 0; i <= 50; i++) {
gfx->drawLine(random(canvasWidth), random(canvasHeight), random(canvasWidth), random(canvasHeight), 1);
}
gfx->setFont(&PermanentMarker_Regular20pt7b);
gfx->setTextSize(1);
gfx->setTextWrap(0); // 1 for wrapping, 0 for clipping
gfx->setTextColor(1); // text, bg....1=black, 0=white
gfx->setCursor(40, canvasHeight * .25);
gfx->fillRoundRect(20, (canvasHeight * .25) - 40, canvasWidth - 40, 60, 20, 0); // xpos, ypos, x_width, y_height, radius, color
gfx->print("Hello World!!!");
gfx->setTextColor(0); // text, bg....1=black, 0=white
gfx->setCursor(40, canvasHeight * .5);
gfx->fillRoundRect(20, (canvasHeight * .5) - 40, canvasWidth - 40, 60, 20, 1); // xpos, ypos, x_width, y_height, radius, color
gfx->print("Hello World!!!");
gfx->setTextColor(1); // text, bg....1=black, 0=white
gfx->setCursor(40, canvasHeight * .75);
gfx->fillRoundRect(20, (canvasHeight * .75) - 40, canvasWidth - 40, 60, 20, 0); // xpos, ypos, x_width, y_height, radius, color
gfx->print("Hello World!!!");
PrintDefinedCanvas(TPChar); // Print the canvas
validprinter = false;
Serial.println("DONE PRINTING...................\n\n\n\n\n");
}
BLE.poll();
peripheral.poll();
delay(10);
}
void setCanvasSize(int width, int height) {
if (width % 8 != 0) {
Serial.println("ERROR: Width must be divisible by 8!");
return;
}
// Free old canvas before creating a new one
if (gfx) {
delete gfx;
gfx = nullptr;
}
// Update canvas size
canvasWidth = width;
canvasHeight = height;
// Allocate new canvas
gfx = new GFXcanvas1(canvasWidth, canvasHeight);
if (!gfx) {
Serial.println("ERROR: Memory allocation failed!");
} else {
Serial.print("Canvas resized: ");
Serial.print(canvasWidth);
Serial.print("x");
Serial.println(canvasHeight);
}
}
void PrintDefinedCanvas(BLECharacteristic TPChar) {
if (!imageData) {
Serial.println("ERROR: Canvas not initialized!");
return;
}
Serial.println("Sending canvas to printer...");
uint8_t gs_v_cmd[] = {
0x1D, 0x76, 0x30, 0x00,
(uint8_t)(canvasWidth / 8), 0,
(uint8_t)(canvasHeight & 0xFF),
(uint8_t)((canvasHeight >> 8) & 0xFF)
};
TPChar.writeValue(gs_v_cmd, sizeof(gs_v_cmd));
Serial.println("GS v 0 command sent");
int index = 0;
for (int y = 0; y < canvasHeight; y++) {
for (int x = 0; x < canvasWidth / 8; x++) {
uint8_t byte = 0;
for (int bit = 0; bit < 8; bit++) {
int pixel = gfx->getPixel(x * 8 + bit, y);
if (pixel > 0) byte |= (1 << (7 - bit));
}
imageData[index++] = byte;
}
}
Serial.println("Canvas converted to raster data");
for (int i = 0; i < (canvasWidth * canvasHeight / 8); i += 100) {
TPChar.writeValue(&imageData[i], min((size_t)100, (size_t)((canvasWidth * canvasHeight / 8) - i)));
delay(10);
}
free(imageData); // Free memory AFTER sending image
imageData = nullptr;
Serial.println("Image printed successfully!");
TPChar.writeValue("\n\n"); // Advance paper
}
void clearCanvas() { // Clears the canvas buffer before drawing
if (!gfx) {
Serial.println("ERROR: Canvas not initialized!");
return;
}
// Clear the canvas before drawing
gfx->fillScreen(0);
// Allocate or resize image buffer dynamically
if (imageData) {
free(imageData);
imageData = nullptr;
}
imageData = (uint8_t *)malloc((canvasWidth * canvasHeight) / 8);
if (!imageData) {
Serial.println("ERROR: Memory allocation failed!");
return;
}
memset(imageData, 0, (canvasWidth * canvasHeight) / 8);
Serial.println("Canvas prepared!");
}
//// Used to find printer being scanned for
void blePeripheralDiscoverHandler(BLEDevice peripheral) {
Serial.println("Discovered BLE event");
BLE.stopScan();
Serial.println("Discovered ...");
if (!peripheral.connected()) {
if (peripheral.connect()) {
Serial.println("Connected");
} else {
Serial.println("Failed to connect!");
return;
}
}
}
// Connects to printer being scanned for and verifies TPServ and TPChar UUIDs //
void blePeripheralConnectHandler(BLEDevice peripheral) {
Serial.println("Connection BLE event");
Serial.println("Discovering attributes ...");
if (peripheral.discoverAttributes()) {
Serial.println("Attributes discovered");
} else {
Serial.println("Attribute discovery failed!");
peripheral.disconnect();
return;
}
Serial.println();
Serial.print("Device name: ");
Serial.println(peripheral.deviceName());
Serial.print("Device address: ");
Serial.println(peripheral.address());
Serial.println();
if (peripheral.hasService("18f0")) {
TPserv = peripheral.service("18f0");
Serial.println("peripheral.service = 18f0");
if (TPserv.hasCharacteristic("2af1")) {
TPChar = TPserv.characteristic("2af1");
Serial.println("TPserv.characteristic = 2af1");
// bool flag to confirm a valid printer is found and connected///
validprinter = true;
} else {
validprinter = false;
peripheral.disconnect();
BLE.scanForAddress(myPrinterAddress, true); ///// starts looking for your printer Address
peripheral = BLE.available();
}
Serial.print("Valid Printer = ");
Serial.println(validprinter);
Serial.println();
}
}
// If printer disconnects, automatically starts searching for it again by myPrinterAddress //
void blePeripheralDisconnectHandler(BLEDevice peripheral) {
Serial.println("Disconnected BLE event");
validprinter = false;
BLE.scanForAddress(myPrinterAddress, true); ///// starts looking for your printer address
peripheral = BLE.available();
}