Components and supplies
Rotary potentiometer (generic)
Arduino MKR WiFi 1010
wooden case
2.13inch E-Ink raw display, three-color
Tools and machines
Soldering iron (generic)
Apps and platforms
Google Forms
Project description
Code
worklogger.ino
arduino
1#include <SPI.h> 2#include<WiFiNINA.h> 3 4// display includes 5#include <fonts.h> 6#include <epdpaint.h> 7#include <epd2in13b.h> 8#include <epdif.h> 9 10 11// ----------------------------------------------------------------------- 12// Variables 13// ----------------------------------------------------------------------- 14 15const int potPin = A1; // potentiometer pin 16int pot_val = 0; // Value of potentiometer pin 17int pot_val_sum = 0; // sum of 10 measures of pot_val 18int current_position; // current position 19int new_position; // position read from poti 20int stable_count = 0; // counts how many times current and new position are the same; 21char ssid[] = "e.g. AndroidAP"; // your network SSID (name) 22char pass[] = "aaa...."; // your network password (use for WPA, or use as key for WEP) 23char server[] = "docs.google.com"; // google forms server 24int status = WL_IDLE_STATUS; // 25WiFiSSLClient client; // client object which does the calls 26 27// --- some variables for the display output 28unsigned long start_time; // stores millis, used to update progress bar 29char progress_bar[9] = "[......]"; // progress bar 30int progress_bar_pos = 1; 31 32#define COLORED 0 33#define UNCOLORED 1 34 35unsigned char image[1024]; 36Paint paint(image, 28,192); //width should be the multiple of 8 37Epd epd; 38// ------- end of display output variables 39 40String jobs[11] = { 41 "A Admin", 42 "A Testing", 43 "A Analysis", 44 "A Coord", 45 "B Admin", 46 "B Coord", 47 "B Analysis", 48 "B Testing", 49 "Internal training", 50 "internal admin", 51 "Pause" 52}; 53 54// ----------------------------------------------------------------------- 55// Functions 56// ----------------------------------------------------------------------- 57/* 58takes value from the poti and returns the position of the pointer 59*/ 60int calculate_position(float val) { 61 int position = 10; 62 if(val < 20) position = 0; 63 else if(val < 96) position = 1; 64 else if(val < 213) position = 2; 65 else if(val < 316) position = 3; 66 else if(val < 458) position = 4; 67 else if(val < 598) position = 5; 68 else if(val < 721) position = 6; 69 else if(val < 838) position = 7; 70 else if(val < 936) position = 8; 71 else if(val < 1010) position = 9; 72 else position = 10; 73 74 return position; 75} 76 77 78/* 79Defines job strings for sending to backend 80*/ 81String storeWork(int pos) { 82 83 // the Serial.print commands are just for debugging. 84 Serial.print("storing job "); 85 Serial.println(jobs[pos]); 86 87 String jobdata = jobs[pos]; 88 jobdata.replace(" ", "%20"); // replace '%20' with empty spaces 89 90 // https://www.instructables.com/id/Post-to-Google-Docs-with-Arduino/ explains how to get the correct 91 // google form url and the endtry id 92 if (client.connectSSL(server, 443)) { 93 client.print("GET http://docs.google.com/forms/d/e/ <id of your google form> /formResponse?entry.<id of your google forms entry field number>="); 94 client.print(jobdata); 95 client.println(" HTTP/1.1"); 96 client.println("Host: docs.google.com"); 97 client.println("Cache-Control: no-cache"); 98 client.println("Connection: close"); 99 client.println(); 100 } 101 // set start time for progress_bar timer 102 start_time = millis(); 103 104 // reset progress Bar 105 for (int i = 1; i < 7; i++) { 106 progress_bar[i] = '.'; 107 } 108 progress_bar_pos = 1; 109 110 111 112 drawString(jobdata); 113 114 // drawProgressBar(); //TODO: uncomment if new display is super fast updating 115 // currently I do not draw a progress bar after selecting a new job 116 117 return "ok"; 118} 119 120/* 121 * Draw String on EPD 122 */ 123void drawString(String jobdata) { 124 // replace %20 125 jobdata.replace("%20", " "); 126 127 // convert String to char Array 128 char jobchars[30]; 129 jobdata.toCharArray(jobchars,30); 130 131 epd.ClearFrame(); 132 paint.SetRotate(ROTATE_90); 133 134 paint.Clear(UNCOLORED); 135 paint.DrawStringAt(8, 2, jobchars, &Font16, COLORED); 136 epd.SetPartialWindowBlack(paint.GetImage(), 50, 16, paint.GetWidth(), paint.GetHeight()); 137 138 epd.DisplayFrame(); 139}; 140 141/* 142 * draw progress bar on EPD 143 */ 144void drawProgressBar() { 145 paint.Clear(UNCOLORED); 146 paint.DrawStringAt(8,2, progress_bar, &Font16, COLORED); 147 epd.SetPartialWindowBlack(paint.GetImage(), 20, 16, paint.GetWidth(), paint.GetHeight()); 148 epd.DisplayFrame(); 149} 150 151/* 152 * update progress_bar string 153 */ 154 void updateProgressBar() { 155 // calculate time_past 156 if (millis() - start_time > 300000) { //do stuff every 5 minutes 157 if (progress_bar_pos < 7) { 158 progress_bar[progress_bar_pos] = '='; 159 progress_bar_pos++; 160 drawProgressBar(); 161 } 162 start_time = millis(); // reset time to current 163 164 } 165 166 } 167 168// ----------------------------------------------------------------------- 169// Setup 170// ----------------------------------------------------------------------- 171void setup() { 172 173 174 pinMode(potPin, INPUT); 175 Serial.begin(9600); 176 delay(1000); 177 178Serial.println("init Display"); 179 // initilize Display 180 181 if (epd.Init() != 0) { 182 Serial.print("e-Paper init failed"); 183 return; 184 } 185 186 // attempt to connect to Wifi network: 187 while (status != WL_CONNECTED) { 188 189 Serial.print("Attempting to connect to SSID: "); 190 Serial.println(ssid); 191 // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 192 status = WiFi.begin(ssid, pass); 193 194 // wait 10 seconds for connection: 195 delay(7000); 196 } 197 Serial.println("Connected to wifi"); 198 199 current_position = -1; 200 201} 202 203// ----------------------------------------------------------------------- 204// Loop 205// ----------------------------------------------------------------------- 206 207void loop() { 208 // read potentiometer value 10 times and get average to flatten out outlier readings 209 // of the potentiometer 210 for (int i = 0; i < 10; i++) { 211 pot_val = analogRead(potPin); 212 pot_val_sum = pot_val_sum + pot_val; 213 } 214 float flat_pot_val = pot_val_sum/10; 215 216 pot_val_sum = 0; // reset to 0 for next loop. 217 218 // Serial.println for debug 219 Serial.println(flat_pot_val); 220 new_position = calculate_position(flat_pot_val); 221 222 // only store new job if potentiometer was not moved for one second 223 // like this I avoid storing several jobs when the user turns the knob all over 224 // the scale 225 if (new_position != current_position) { 226 stable_count = 0; 227 } 228 if (stable_count == 1) { 229 storeWork(new_position); 230 } 231 current_position = new_position; 232 stable_count++; 233 234 // update progress bar 235 updateProgressBar(); 236 237 delay(1000); 238}
worklogger.ino
arduino
1#include <SPI.h> 2#include<WiFiNINA.h> 3 4// display includes 5#include 6 <fonts.h> 7#include <epdpaint.h> 8#include <epd2in13b.h> 9#include <epdif.h> 10 11 12// 13 ----------------------------------------------------------------------- 14// Variables 15// 16 ----------------------------------------------------------------------- 17 18const 19 int potPin = A1; // potentiometer pin 20int pot_val = 0; // 21 Value of potentiometer pin 22int pot_val_sum = 0; // sum of 10 measures 23 of pot_val 24int current_position; // current position 25int new_position; 26 // position read from poti 27int stable_count = 0; // 28 counts how many times current and new position are the same; 29char ssid[] = "e.g. 30 AndroidAP"; // your network SSID (name) 31char pass[] = "aaa...."; // 32 your network password (use for WPA, or use as key for WEP) 33char server[] = "docs.google.com"; 34 // google forms server 35int status = WL_IDLE_STATUS; // 36WiFiSSLClient client; 37 // client object which does the calls 38 39// --- some variables for 40 the display output 41unsigned long start_time; // stores millis, used to 42 update progress bar 43char progress_bar[9] = "[......]"; // progress bar 44int 45 progress_bar_pos = 1; 46 47#define COLORED 0 48#define UNCOLORED 1 49 50unsigned 51 char image[1024]; 52Paint paint(image, 28,192); //width should be the multiple 53 of 8 54Epd epd; 55// ------- end of display output variables 56 57String jobs[11] 58 = { 59 "A Admin", 60 "A Testing", 61 "A Analysis", 62 "A Coord", 63 64 "B Admin", 65 "B Coord", 66 "B Analysis", 67 "B Testing", 68 "Internal 69 training", 70 "internal admin", 71 "Pause" 72}; 73 74// ----------------------------------------------------------------------- 75// 76 Functions 77// ----------------------------------------------------------------------- 78/* 79takes 80 value from the poti and returns the position of the pointer 81*/ 82int calculate_position(float 83 val) { 84 int position = 10; 85 if(val < 20) position = 0; 86 else if(val 87 < 96) position = 1; 88 else if(val < 213) position = 2; 89 else if(val < 316) 90 position = 3; 91 else if(val < 458) position = 4; 92 else if(val < 598) position 93 = 5; 94 else if(val < 721) position = 6; 95 else if(val < 838) position = 7; 96 97 else if(val < 936) position = 8; 98 else if(val < 1010) position = 9; 99 else 100 position = 10; 101 102 return position; 103} 104 105 106/* 107Defines job strings 108 for sending to backend 109*/ 110String storeWork(int pos) { 111 112 // the Serial.print 113 commands are just for debugging. 114 Serial.print("storing job "); 115 Serial.println(jobs[pos]); 116 117 118 String jobdata = jobs[pos]; 119 jobdata.replace(" ", "%20"); // replace 120 '%20' with empty spaces 121 122 // https://www.instructables.com/id/Post-to-Google-Docs-with-Arduino/ 123 explains how to get the correct 124 // google form url and the endtry id 125 if 126 (client.connectSSL(server, 443)) { 127 client.print("GET http://docs.google.com/forms/d/e/ 128 <id of your google form> /formResponse?entry.<id of your google forms entry field 129 number>="); 130 client.print(jobdata); 131 client.println(" HTTP/1.1"); 132 133 client.println("Host: docs.google.com"); 134 client.println("Cache-Control: 135 no-cache"); 136 client.println("Connection: close"); 137 client.println(); 138 139 } 140 // set start time for progress_bar timer 141 start_time = millis(); 142 143 144 // reset progress Bar 145 for (int i = 1; i < 7; i++) { 146 progress_bar[i] 147 = '.'; 148 } 149 progress_bar_pos = 1; 150 151 152 153 drawString(jobdata); 154 155 156 // drawProgressBar(); //TODO: uncomment if new display is super fast updating 157 158 // currently I do not draw a progress bar after selecting a new job 159 160 161 return "ok"; 162} 163 164/* 165 * Draw String on EPD 166 */ 167void drawString(String 168 jobdata) { 169 // replace %20 170 jobdata.replace("%20", " "); 171 172 // 173 convert String to char Array 174 char jobchars[30]; 175 jobdata.toCharArray(jobchars,30); 176 177 178 epd.ClearFrame(); 179 paint.SetRotate(ROTATE_90); 180 181 paint.Clear(UNCOLORED); 182 183 paint.DrawStringAt(8, 2, jobchars, &Font16, COLORED); 184 epd.SetPartialWindowBlack(paint.GetImage(), 185 50, 16, paint.GetWidth(), paint.GetHeight()); 186 187 epd.DisplayFrame(); 188}; 189 190/* 191 192 * draw progress bar on EPD 193 */ 194void drawProgressBar() { 195 paint.Clear(UNCOLORED); 196 197 paint.DrawStringAt(8,2, progress_bar, &Font16, COLORED); 198 epd.SetPartialWindowBlack(paint.GetImage(), 199 20, 16, paint.GetWidth(), paint.GetHeight()); 200 epd.DisplayFrame(); 201} 202 203/* 204 205 * update progress_bar string 206 */ 207 void updateProgressBar() { 208 // calculate 209 time_past 210 if (millis() - start_time > 300000) { //do stuff every 5 minutes 211 212 if (progress_bar_pos < 7) { 213 progress_bar[progress_bar_pos] = '='; 214 215 progress_bar_pos++; 216 drawProgressBar(); 217 } 218 start_time 219 = millis(); // reset time to current 220 221 } 222 223 } 224 225// ----------------------------------------------------------------------- 226// 227 Setup 228// ----------------------------------------------------------------------- 229void 230 setup() { 231 232 233 pinMode(potPin, INPUT); 234 Serial.begin(9600); 235 delay(1000); 236 237Serial.println("init 238 Display"); 239 // initilize Display 240 241 if (epd.Init() != 0) { 242 Serial.print("e-Paper 243 init failed"); 244 return; 245 } 246 247 // attempt to connect to Wifi 248 network: 249 while (status != WL_CONNECTED) { 250 251 Serial.print("Attempting 252 to connect to SSID: "); 253 Serial.println(ssid); 254 // Connect to WPA/WPA2 255 network. Change this line if using open or WEP network: 256 status = WiFi.begin(ssid, 257 pass); 258 259 // wait 10 seconds for connection: 260 delay(7000); 261 } 262 263 Serial.println("Connected to wifi"); 264 265 current_position = -1; 266 267} 268 269// 270 ----------------------------------------------------------------------- 271// Loop 272// 273 ----------------------------------------------------------------------- 274 275void 276 loop() { 277 // read potentiometer value 10 times and get average to flatten out 278 outlier readings 279 // of the potentiometer 280 for (int i = 0; i < 10; i++) 281 { 282 pot_val = analogRead(potPin); 283 pot_val_sum = pot_val_sum + pot_val; 284 285 } 286 float flat_pot_val = pot_val_sum/10; 287 288 pot_val_sum = 0; // reset 289 to 0 for next loop. 290 291 // Serial.println for debug 292 Serial.println(flat_pot_val); 293 294 new_position = calculate_position(flat_pot_val); 295 296 // only store new job 297 if potentiometer was not moved for one second 298 // like this I avoid storing 299 several jobs when the user turns the knob all over 300 // the scale 301 if (new_position 302 != current_position) { 303 stable_count = 0; 304 } 305 if (stable_count == 306 1) { 307 storeWork(new_position); 308 } 309 current_position = new_position; 310 311 stable_count++; 312 313 // update progress bar 314 updateProgressBar(); 315 316 317 delay(1000); 318}
Downloadable files
full version including e-paper
This schematic shows the full version including the e-paper hat wirings. Since the Arduino MKR 1010 WIFI uses SPI to communicate to the WiFi module, I ran into SPI pin conflicts. So I had to change the Pin definition of my epd2in13b library for the waveshare disply. I changed the file 'epdif.h' like this: // Pin definition #define RST_PIN 6 #define DC_PIN 5 #define CS_PIN 4 #define BUSY_PIN 7
full version including e-paper
full version including e-paper
This schematic shows the full version including the e-paper hat wirings. Since the Arduino MKR 1010 WIFI uses SPI to communicate to the WiFi module, I ran into SPI pin conflicts. So I had to change the Pin definition of my epd2in13b library for the waveshare disply. I changed the file 'epdif.h' like this: // Pin definition #define RST_PIN 6 #define DC_PIN 5 #define CS_PIN 4 #define BUSY_PIN 7
full version including e-paper
easy version without display
Wiring of the easy version just having a potentiometer as a turn knob, without the e-paper display.
easy version without display
Comments
Only logged in users can leave comments