Work Logger - Log Your Daily Work With A Turn Of A Knob
About the project
The Work Logger helps you log your daily work without any effort - no more spreadsheets needed.
Project info
Difficulty: Moderate
Platforms: Arduino
Estimated time: 1 day
License: Creative Commons Attribution CC BY version 4.0 or later (CC BY 4+)
Items used in this project
Hardware components
Story
ABOUT THIS PROJECT
The Work Logger is a little everyday helper to log my working time. It tracks WHEN I am doing WHAT. And it does this with just little turn of a knob.
Problem
As a business analyst, I work in different projects. And in those projects I do different things. At the end of the day I try to remember what I spent my working time on - which is usually not easy after a long day. I used pen and paper, spread sheets and other tools, but they all somehow involved to much effort to use them.
Solution
The hardware Work Logger is basically a turn knob that points to what I am currently working at. So it takes one turn to record my work. As soon as I do not turn the potentiometer any more for 3 seconds it sends the current work position to a Google Forms questionnaire. Google takes care of adding a timestamp. At the end of the day I have a list of my jobs done on a Google spreadsheet.
CODE
worklogger.ino Arduino
- #include <SPI.h>
- #include<WiFiNINA.h>
- // display includes
- #include <fonts.h>
- #include <epdpaint.h>
- #include <epd2in13b.h>
- #include <epdif.h>
- // -----------------------------------------------------------------------
- // Variables
- // -----------------------------------------------------------------------
- const int potPin = A1; // potentiometer pin
- int pot_val = 0; // Value of potentiometer pin
- int pot_val_sum = 0; // sum of 10 measures of pot_val
- int current_position; // current position
- int new_position; // position read from poti
- int stable_count = 0; // counts how many times current and new position are the same;
- char ssid[] = "e.g. AndroidAP"; // your network SSID (name)
- char pass[] = "aaa...."; // your network password (use for WPA, or use as key for WEP)
- char server[] = "docs.google.com"; // google forms server
- int status = WL_IDLE_STATUS; //
- WiFiSSLClient client; // client object which does the calls
- // --- some variables for the display output
- unsigned long start_time; // stores millis, used to update progress bar
- char progress_bar[9] = "[......]"; // progress bar
- int progress_bar_pos = 1;
- #define COLORED 0
- #define UNCOLORED 1
- unsigned char image[1024];
- Paint paint(image, 28,192); //width should be the multiple of 8
- Epd epd;
- // ------- end of display output variables
- String jobs[11] = {
- "A Admin",
- "A Testing",
- "A Analysis",
- "A Coord",
- "B Admin",
- "B Coord",
- "B Analysis",
- "B Testing",
- "Internal training",
- "internal admin",
- "Pause"
- };
- // -----------------------------------------------------------------------
- // Functions
- // -----------------------------------------------------------------------
- /*
- takes value from the poti and returns the position of the pointer
- */
- int calculate_position(float val) {
- int position = 10;
- if(val < 20) position = 0;
- else if(val < 96) position = 1;
- else if(val < 213) position = 2;
- else if(val < 316) position = 3;
- else if(val < 458) position = 4;
- else if(val < 598) position = 5;
- else if(val < 721) position = 6;
- else if(val < 838) position = 7;
- else if(val < 936) position = 8;
- else if(val < 1010) position = 9;
- else position = 10;
- return position;
- }
- /*
- Defines job strings for sending to backend
- */
- String storeWork(int pos) {
- // the Serial.print commands are just for debugging.
- Serial.print("storing job ");
- Serial.println(jobs[pos]);
- String jobdata = jobs[pos];
- jobdata.replace(" ", "%20"); // replace '%20' with empty spaces
- // https://www.instructables.com/id/Post-to-Google-Docs-with-Arduino/ explains how to get the correct
- // google form url and the endtry id
- if (client.connectSSL(server, 443)) {
- 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>=");
- client.print(jobdata);
- client.println(" HTTP/1.1");
- client.println("Host: docs.google.com");
- client.println("Cache-Control: no-cache");
- client.println("Connection: close");
- client.println();
- }
- // set start time for progress_bar timer
- start_time = millis();
- // reset progress Bar
- for (int i = 1; i < 7; i++) {
- progress_bar[i] = '.';
- }
- progress_bar_pos = 1;
- drawString(jobdata);
- // drawProgressBar(); //TODO: uncomment if new display is super fast updating
- // currently I do not draw a progress bar after selecting a new job
- return "ok";
- }
- /*
- * Draw String on EPD
- */
- void drawString(String jobdata) {
- // replace %20
- jobdata.replace("%20", " ");
- // convert String to char Array
- char jobchars[30];
- jobdata.toCharArray(jobchars,30);
- epd.ClearFrame();
- paint.SetRotate(ROTATE_90);
- paint.Clear(UNCOLORED);
- paint.DrawStringAt(8, 2, jobchars, &Font16, COLORED);
- epd.SetPartialWindowBlack(paint.GetImage(), 50, 16, paint.GetWidth(), paint.GetHeight());
- epd.DisplayFrame();
- };
- /*
- * draw progress bar on EPD
- */
- void drawProgressBar() {
- paint.Clear(UNCOLORED);
- paint.DrawStringAt(8,2, progress_bar, &Font16, COLORED);
- epd.SetPartialWindowBlack(paint.GetImage(), 20, 16, paint.GetWidth(), paint.GetHeight());
- epd.DisplayFrame();
- }
- /*
- * update progress_bar string
- */
- void updateProgressBar() {
- // calculate time_past
- if (millis() - start_time > 300000) { //do stuff every 5 minutes
- if (progress_bar_pos < 7) {
- progress_bar[progress_bar_pos] = '=';
- progress_bar_pos++;
- drawProgressBar();
- }
- start_time = millis(); // reset time to current
- }
- }
- // -----------------------------------------------------------------------
- // Setup
- // -----------------------------------------------------------------------
- void setup() {
- pinMode(potPin, INPUT);
- Serial.begin(9600);
- delay(1000);
- Serial.println("init Display");
- // initilize Display
- if (epd.Init() != 0) {
- Serial.print("e-Paper init failed");
- return;
- }
- // attempt to connect to Wifi network:
- while (status != WL_CONNECTED) {
- Serial.print("Attempting to connect to SSID: ");
- Serial.println(ssid);
- // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
- status = WiFi.begin(ssid, pass);
- // wait 10 seconds for connection:
- delay(7000);
- }
- Serial.println("Connected to wifi");
- current_position = -1;
- }
- // -----------------------------------------------------------------------
- // Loop
- // -----------------------------------------------------------------------
- void loop() {
- // read potentiometer value 10 times and get average to flatten out outlier readings
- // of the potentiometer
- for (int i = 0; i < 10; i++) {
- pot_val = analogRead(potPin);
- pot_val_sum = pot_val_sum + pot_val;
- }
- float flat_pot_val = pot_val_sum/10;
- pot_val_sum = 0; // reset to 0 for next loop.
- // Serial.println for debug
- Serial.println(flat_pot_val);
- new_position = calculate_position(flat_pot_val);
- // only store new job if potentiometer was not moved for one second
- // like this I avoid storing several jobs when the user turns the knob all over
- // the scale
- if (new_position != current_position) {
- stable_count = 0;
- }
- if (stable_count == 1) {
- storeWork(new_position);
- }
- current_position = new_position;
- stable_count++;
- // update progress bar
- updateProgressBar();
- delay(1000);
- }
SCHEMATICS
easy version without display
Wiring of the easy version just having a potentiometer as a turn knob, without the e-paper display.
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
Leave your feedback...