Can I make a small windows app for taking time and log production times?

Hi!

First of all. Is it possible to export/save a finished program to open in windows without processing?

What I would like is a windows app for logging times for different articles.
So. I need the option to add a number and save it so I can re use it. This would be a article number.

I would then need to search and chose a article number and with a number chosen, start a timer.
When the timer is started I would like to go back and enter another article. I need the ability to count several articles at once.

Then. When I enter a article number that is in counting mode I would like the option to stop.
When the timer is stopped I would need to be able to see the time… Either by the app sending it in a mail and then forgetting about it or of I can save the data and in the app go in a article and show all times measured.

Is this possible with processing? Do you get what I would like to make?.
If possible, is it novice, intermediate och advanced coding?

yes and no

you can export to .exe and distribute and run
( but it will include processing )
BUT not the PDE.

so now play:
use any example or own code
/ File / Export Application /
select OS like “Windows”, use EMBED JAVA

find under OS Win 64 / sketch.exe and double click

as processing and JAVA is included it will NOT be small ?200mb?

1 Like

Cool!
Ill have to try this later on a random code to see how it looks and works.
Thx.

About my longer question… Is it possible to make something like this? And is it possible to make it as a small project?

did you already break it down into steps?

-1- read write CSV file
-2- select + show ‘table’ records on screen
-3- allow text field with number input from keyboard
-4- create timestamps ( of now ) save to record / save to file
so later spreadsheet will understand that date-time correctly.

1 Like

I am not sure I understand.

Let’s say you work on article A on five different days for each 10 minutes. Is it enough that you store 50 minutes and we just add the times up OR do you need a log where it says on day 1 ten minutes, day 2 ten minutes and so forth?

1 Like

Well. I don’t really know what the different steps could look like and how to make it work? So, no… I haven’t :joy:
Your example looks interesting. I was just thinking about the possibilities to keep the records even after quitting the app. It would need some kind of function to create a new timer for every product number added and than save this to use several times and with its history…

Yeah… I would like to be able to see the time for each event separate. That time divided with the number of products produced gives a cycle time.:blush:

yes exactly

-1- CSV file

show us your code

but start designing the CSV file ( as only you can design your database )
including record content ( columns ) and lines ( rows ) for each event?
and in my above PLAN that has not much to do with the processing
program structure/code

you can make it from spreadsheet, or just edit with notepad, does not matter.
but get it into /data/myTable.csv
and read it into processing
first step just print to console:

  • number rows,
  • number columns,
  • column names
  • and all rows content. ( learn the different concepts of dealing with table / addressing 2D array )
2 Likes

imho you would then use JSON instead of csv because you need a complex list of events for each article…

1 Like

I get the feeling I’m a bit to novice for this right now. I haven’t got to that part in the processing book jet🤓

However. I won’t be able to let this go. I just need to down prioritize it for now so if you have any good example you know of that I could look and learn from it would be interesting.

In my case. The information I want to collect is how long operations take in a process on the factory floor.
For every production event and for the whole product in total I would like to be able to see:

  • Setup time
  • Total time
    *Cycle time
  • Produced parts in total
  • Parts destroyed by setup
  • Faulty parts
  • Parts produced and ok for next operation
  • Dates and times
  • User ID’s

I will give you an example in a second

(I was writing my sketch prior to reading your last posts so it’s mainly addressing your initial information)

1 Like

here you go

(at this time I thought you mean article like an article in a newspaper)

you can

  • hit r at first run. - test data gets made and saved
  • use l - load - to load it
  • Use s to save

then

  • Use cursor left and right now.
  • Use + to add article.
  • Use Space Bar to start timer (referring to currently visible article) and e to end it.

Remark

to be honest, when you plan this for a real factory, this is not the way to go.

I mean there are databases like Microsoft Access for this purpose

also, when you have a factory with machines, you would to integrate the measuring with the machines there. Or with the humans.

Further questions after writing this sketch

You wrote:

Let me comment on this.

Let me understand the scenario first.
When the whole product is a Left Car Door
and every production event is one door that is finished.
So we measure the time each door needs and the average etc.

Is that scenario correct?

Detail Questions

You wrote you need the data for both, every production event AND for the whole product in total. I don’t think that is true. We have to distinguish beetween both. And save separately.

  • Setup time: Makes sense only for production event imo.
  • Total time: Makes sense for both.
  • Cycle time:What is it, average for one door?
  • Produced parts in total: makes sense only for the whole product imo.
  • Parts destroyed by setup. makes sense only for the whole product imo.
  • Faulty parts. makes sense only for the whole product imo.
  • Parts produced and ok for next operation. makes sense only for the whole product imo.
  • Dates and times. Makes sense for both.
  • User ID’s. Makes sense for both.

Am I correct in this?

Chrisir



// states 
final int normal=0; 
final int newArticleEnterName=1;
int state=normal;

// Main list of articles 
JSONArray valuesArray1;

// for loading 
boolean loaded=false; 
int loadedIndex=0; // index referring to valuesArray1

// vars for making a new article (+)
String newArticleName="";

// vars for measuring Time (Space Bar and e)
boolean measuringTime=false;
int measuringTimeIndex=0;
String dateNew  ="";
String timeNew  ="";
String dateNew2 ="";
String timeNew2 ="";

void setup() {
  size(1200, 600);
}

void draw() {
  background(0);

  switch(state) {
  case normal:
    text("r for test data (these are saved), s to save, l to load", 14, 14);
    showLoadedScreen();
    break; 

  case newArticleEnterName:
    text("Enter new Name: "+newArticleName, 114, 114);
    text("You can use Backspace. Submit with Enter.", 114, 214);
    break;
  }//switch
  //
}

// -------------------------------------------------------------------------------------------

void showLoadedScreen() {
  if (loaded) {
    //
    text("You loaded the file. Use cursor left and right now. "
      +"Use + to add article. "
      +"Use Space Bar to start timer and e to end it.", 
      214, 34);

    if (measuringTime) {
      text("measuring Time for \n"
        +measuringTimeIndex, width-200, 200);
    }

    JSONObject currentArticle = valuesArray1.getJSONObject(loadedIndex); 

    int id = currentArticle.getInt("id");
    String articleName = currentArticle.getString("article");
    String number = currentArticle.getString("number");
    JSONArray eventsArray=currentArticle.getJSONArray("events");
    String eventsMessage="";
    if (eventsArray==null) {
      eventsMessage=" Empty ";
    } 
    text(id +"\narticle name "+articleName +" ("+number+")\nEvents:"+eventsMessage, 
      33, 44);

    int lineNumber=0; 
    if (eventsArray!=null) {
      for (int i = 0; i < eventsArray.size(); i++) {

        JSONObject event1 = eventsArray.getJSONObject(i); 

        int idEvent = event1.getInt("id");
        String date = event1.getString("date");
        String time = event1.getString("time");
        String[] timeData = split (time, '-');
        text(idEvent+". "+date+": time: "+timeData[0] + " to " +timeData[1], 
          55, 100+lineNumber*13);
        lineNumber++;
      }
    }
  }
}

// -------------------------------------------------------------------------------

void keyPressed() {
  // depending on state 
  switch(state) {
  case normal:
    keyPressedNormal() ;
    break; 

  case newArticleEnterName:
    keyPressedNewArticleEnterName() ;
    break;
  }
}

//-----------------------

void keyPressedNewArticleEnterName() {
  if (!loaded) 
    return;//leave

  switch(key) {
  case ENTER:
  case RETURN:
    // end of entering a new name 
    state=normal;

    JSONObject article = new JSONObject();

    article.setInt("id", valuesArray1.size());
    article.setString("article", newArticleName);
    article.setString("number", str(valuesArray1.size()));

    JSONArray eventsArray=null;
    article.setJSONArray("events", eventsArray);

    valuesArray1.setJSONObject(valuesArray1.size(), article);
    break;

  case BACKSPACE:
    if (newArticleName.length()<=0)return;
    newArticleName=newArticleName.substring(0, newArticleName.length()-1);
    break; 

  default:
    if (key==CODED)
      return; // leave 
    newArticleName+=key; 
    break;
  }//switch
}//func

void keyPressedNormal() {

  if (key!=CODED) {

    switch(key) {

    case 'r':
      // make all pseudo articles from scratch and save them
      String[] articleNames = { "Climate", "Work", "Music" };
      String[] articleNumbers = { "0", "1", "2" };

      valuesArray1 = new JSONArray();

      for (int i = 0; i < articleNames.length; i++) {

        JSONObject article = new JSONObject();

        article.setInt("id", i);
        article.setString("article", articleNames[i]);
        article.setString("number", articleNumbers[i]);

        JSONArray eventsArray=getEvents(i); // that's test data
        article.setJSONArray("events", eventsArray);

        valuesArray1.setJSONObject(i, article);
      }

      saveJSONArray(valuesArray1, "data/new.json");
      println("saved");
      break;

    case 's':
      //save
      saveJSONArray(valuesArray1, "data/new.json");
      println("saved");
      break;

    case 'l':
      //load 
      valuesArray1 = loadJSONArray("new.json");
      loaded=true;
      loadedIndex=0;
      println("loaded");
      //
      break;

    case '+':
      if (!loaded) 
        return;//leave
      state=newArticleEnterName; 
      break;

    case ' ':
      // start
      dateNew = day()+"/"+month()+"/"+year();
      println(dateNew);
      timeNew = hour() +":"+minute();
      println(timeNew);
      measuringTime=true;
      measuringTimeIndex = loadedIndex; 
      break;

    case 'e':
      //stop
      dateNew2 = day()+"/"+month()+"/"+year();
      println(dateNew2);
      timeNew2 = hour() +":"+minute();
      println(timeNew2);
      measuringTime=false;

      JSONObject currentArticle = valuesArray1.getJSONObject(measuringTimeIndex); 
      JSONArray eventsArray=currentArticle.getJSONArray("events");

      JSONObject event1 = new JSONObject();

      int newID=0;
      if (eventsArray!=null) 
        newID=eventsArray.size();
      event1.setInt("id", newID);
      event1.setString("date", dateNew);// assuming both dates dateNew and dateNew2 are the same!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      event1.setString("time", timeNew+"-"+timeNew2);

      if (eventsArray==null) {
        eventsArray = new JSONArray();
        currentArticle.setJSONArray("events", eventsArray);
        eventsArray.setJSONObject(newID, event1);
      } else {
        eventsArray.setJSONObject(newID, event1);
      }
      break;
    }//switch
  }//if
  //----------------------------------------------
  else {
    if (!loaded) 
      return;//leave

    switch(keyCode) {
    case LEFT:
      loadedIndex--;
      if (loadedIndex<0)
        loadedIndex=0;
      break; 

    case RIGHT:
      loadedIndex++;
      if (loadedIndex>=valuesArray1.size()) {
        loadedIndex=valuesArray1.size()-1;
        println("Last");
      }//inner if 
      break;
      //
    }//switch
  }//else
}//func 

JSONArray getEvents(int indexOfArticle) {
  // test data 

  if (indexOfArticle==0) {

    JSONArray eventsArray = new JSONArray();

    String[] articleNames2 = { "11/09/2019", "13/09/2019", "17/09/2019" };
    String[] articleNumbers2 = { "03:04-05:47", "13:19-18:44", "22:33-23:12" };

    for (int i = 0; i < articleNames2.length; i++) {

      JSONObject event1 = new JSONObject();

      event1.setInt("id", i);
      event1.setString("date", articleNames2[i]);
      event1.setString("time", articleNumbers2[i]);

      eventsArray.setJSONObject(i, event1);
    }

    return eventsArray;
  } else if (indexOfArticle==1) {
    JSONArray eventsArray = new JSONArray();

    String[]  articleNames2 = { "11/09/2014", "13/09/2015", "17/09/2016" };
    String[]  articleNumbers2 = { "03:04-05:47", "13:19-18:44", "12:33-13:12" };

    for (int i = 0; i < articleNames2.length; i++) {

      JSONObject event1 = new JSONObject();

      event1.setInt("id", i);
      event1.setString("date", articleNames2[i]);
      event1.setString("time", articleNumbers2[i]);

      eventsArray.setJSONObject(i, event1);
    }

    return eventsArray;
  } else if (indexOfArticle==2) {
    JSONArray eventsArray = new JSONArray();

    String[] articleNames2 = { "11/09/2011", "13/09/2011", "17/09/2011" };
    String[] articleNumbers2 = { "03:04-05:47", "13:19-18:44", "22:33-23:12" };

    for (int i = 0; i < articleNames2.length; i++) {

      JSONObject event1 = new JSONObject();

      event1.setInt("id", i);
      event1.setString("date", articleNames2[i]);
      event1.setString("time", articleNumbers2[i]);

      eventsArray.setJSONObject(i, event1);
    }

    return eventsArray;
  } else {
    JSONArray eventsArray = new JSONArray();

    String[] articleNames2 = { "11/09/19", "13/09/19", "17/09/19" };
    String[] articleNumbers2 = { "03:04-05:47", "13:19-18:44", "22:33-23:12" };

    for (int i = 0; i < articleNames2.length; i++) {

      JSONObject event1 = new JSONObject();

      event1.setInt("id", i);
      event1.setString("date", articleNames2[i]);
      event1.setString("time", articleNumbers2[i]);

      eventsArray.setJSONObject(i, event1);
    }

    return eventsArray;
  }//else
}
//
2 Likes

here is a typical json that results


[
  {
    "number": "0",
    "id": 0,
    "article": "Climate",
    "events": [
      {
        "date": "11/09/2019",
        "id": 0,
        "time": "03:04-05:47"
      },
      {
        "date": "13/09/2019",
        "id": 1,
        "time": "13:19-18:44"
      },
      {
        "date": "17/09/2019",
        "id": 2,
        "time": "22:33-23:12"
      },
      {
        "date": "15/11/2019",
        "id": 3,
        "time": "17:53-17:53"
      }
    ]
  },
  {
    "number": "1",
    "id": 1,
    "article": "Work",
    "events": [
      {
        "date": "11/09/2014",
        "id": 0,
        "time": "03:04-05:47"
      },
      {
        "date": "13/09/2015",
        "id": 1,
        "time": "13:19-18:44"
      },
      {
        "date": "17/09/2016",
        "id": 2,
        "time": "12:33-13:12"
      }
    ]
  },
  {
    "number": "2",
    "id": 2,
    "article": "Music",
    "events": [
      {
        "date": "11/09/2011",
        "id": 0,
        "time": "03:04-05:47"
      },
      {
        "date": "13/09/2011",
        "id": 1,
        "time": "13:19-18:44"
      },
      {
        "date": "17/09/2011",
        "id": 2,
        "time": "22:33-23:12"
      }
    ]
  },
  {
    "number": "3",
    "id": 3,
    "article": "Nature",
    "events": [{
      "date": "15/11/2019",
      "id": 0,
      "time": "17:53-17:53"
    }]
  }
]
1 Like

Hi!

First of all. Thank you so much for this example code… really cool of you to make this :slight_smile:

I’ll start off by answering your questions :slightly_smiling_face:
Oh… and im sorry for the confusion around the word “article”… translation error from my side!..

I need to measure on component level only. How long it takes to produce a part.
The whole product is a work chair and I need to see how long it takes to make a backrest or assemble the wheels for example.
My idea is that when a person start the job like they do today, by printing out the order, he or she could also start the timer. When the operator is done he or she will stop the timer and also type in some data about number of parts.
The order might have been for 30 components so the time is the total time for this order that we then divide by the number of components to get how long each component took.

  • Setup time: How long does it take from when I stop job 1 until I start producing in job 2. Thes is a very interesting time to have and often a big area of improvement in production. It would be great to have the option to start the setup time as a step 1 in the counter. Then when the setup is done the operator press “start” and a new counter starts from zero. Like lap times. Every order could have a 2 step counter. Example: Chose job and start > setting up the job > stop job > enter number of setup parts > start again > producing parts > stops the job > enter number of parts that are ok > entering number of parts faulty > save… And start all over with a ne order :slight_smile:
  • Total time: The time from when I start the job until I stop it. Time shown like: hours:minutes:seconds (all times).
  • Cycle time: If the job is to make 10 “doors” and takes 10 min, the cycle time is 1 min. The time fore every part.
  • Produced parts in total: How many parts were produced in the job. This data has to be put in by the operator.
  • Parts destroyed by setup. In the setup there may be parts destroyed. This also has to be put in manually by an operator.
  • Faulty parts. During the job something may go wrong. This has to be reported manually by a operator.
  • Parts produced and ok for next operation. This also has to be typed in manually by the operator. The number of parts actually ok to use for the next operation. If this operation was welding. Next operation will be powder coating.
  • Dates and times. For tracking history. The times for jobs is better shown like from a timer. Hours:minutes:seconds.
  • User ID’s. For the ability to track who was taking the time.

Your code looks amazing.
I dont get exactly how it works but Im moving forward in my studying so soon I will :slight_smile:

I ran the program and it works. It didn’s save the data tough?
I tried creating a new “order”/“part”/“article” and taking time than saving and closing the program.
After opening again the new order was there but no history of times?.

Is it possible to time several things at once? In the program now it seems like only one is activated and if I start another that one takes over?. :slight_smile:

Thanks for coming back to this!

I worked further on this, when you are interested.

You have to use s to save. No automatic save.

Then you have to use load (use l) and not r (test data)

The history should be there

Not possible at the moment

1 Like

So chair doesn’t occur in the sketch but only backrest, wheels etc.?

So timing is always for backrest, wheels etc.?

Does this mean, 2 backrests parallel at once OR a backrest and a wheel?

1 Like

I’m sorry for my delayed respons on your previous post, with the code and everything.:cry: From time to time I have way to many projects going on, both at work and on my free time. This is by far the most interesting project! It shows a whole new area of the processing software for me and making it even more inspiring to learn more. :slight_smile:
I really appreciate the time and help :grinning:

So… about the timer.
No. The finished product is a chair made from a lot of different parts. I will never be able to map “how long does it take to make a chair” cause of all the different configuration it has.
What is interesting is how long it takes to make each part.
With that information we can make sure the planning is more correct and we can make sure the parts have the correct value based on the time. Most important from my point as a production engineer, we can see how the improvements we make in the production works out. Also its a great way to see bottle neck operations. The operations that takes longer that the ones around it. When we find those we can focus on improving them and add more resources to them.
This is why I want the timer to focus on parts and not on the finished product. :slight_smile:

About measuring several times at once. There are several operations going on at the same time. Someone is drilling holes, someone is welding something and someone else is assembling something. We have a couple of PC’s running on the floor but not every operation has its own so there operators will go to the same PC and see the same timer program.
If its not possible to run several operations at the same time Ill just focus on one group per week or something like that but running several at once would definitely speed things up getting the times needed for starting improvement work at the correct spots. :slight_smile:

The parts is named with number like “805216” and we have a couple :stuck_out_tongue:
If its possible to list all parts in falling order alternative have a way of searching it would be awesome.

1 Like

To be honest, I worked further on this

But in the end I think you should do it in MS Access as I wrote above

I see several problems:

  • you have different computers using the same json database at the same time and different users

  • You can’t make flexible reports or print something

1 Like

The different computers doesn’t have to run the same database.
If there is a option to export data from each computer I could do that trip around the floor collecting from the computers on Fridays. :slight_smile:

1 Like

This has been going on via e-mail and is now a pretty long Sketch

Ask when interested

1 Like