Понадобился мне счётчик человеко-часов.
Для чего? Вот есть сложное техническое устройство. В один момент над ним могут трудиться до 4х специалистов. Как посчитать стоимость работы? Возле каждого человека с секундомером не приставишь. А им тоже есть чем заняться, чтобы какой-то журнал вести. Итак:
1. Ардуино нано.
2. Модуль реального времени.
3. Модуль SD карты памяти.
4. TFT дисплей 240х320.
5. Модуль питания.
5. АКБ от старого бесперебойника.
Идея простая.
Рядом с объектом стоит коробка с четырьмя обычными выключателями. Специалист подходит - включает любой свободный (если не нужно считать отдельно время каждого) или только "свой номер". Какой свободный - видно на экране, горит зелёным. На фото роль выключателей играют 4 чёрных проводка на макетной плате, обведённых жёлтым.
Специалист отвлекается на другую работу, уходит на обед или в любой другой момент, когда перестаёт работать над этим объектом - выключает любой включенный (на экране отмеченный красным), или "свой номер". В этот момент на карту памяти записывается событие: время начала, время окончания, количество секунд сессии.
Данные с карты памяти легко импортируются в любой табличный редактор и анализируются.
Надо понимать, что данное изделие не обладает контрольно-надзорным функционалом и никак не защищено от злоупотреблений. Его задача избавить инженерный персонал от учётных процедур, а так же помогать в пересмотре норм на технические операции.
Для чего? Вот есть сложное техническое устройство. В один момент над ним могут трудиться до 4х специалистов. Как посчитать стоимость работы? Возле каждого человека с секундомером не приставишь. А им тоже есть чем заняться, чтобы какой-то журнал вести. Итак:
1. Ардуино нано.
2. Модуль реального времени.
3. Модуль SD карты памяти.
4. TFT дисплей 240х320.
5. Модуль питания.
5. АКБ от старого бесперебойника.
Идея простая.
Рядом с объектом стоит коробка с четырьмя обычными выключателями. Специалист подходит - включает любой свободный (если не нужно считать отдельно время каждого) или только "свой номер". Какой свободный - видно на экране, горит зелёным. На фото роль выключателей играют 4 чёрных проводка на макетной плате, обведённых жёлтым.
Специалист отвлекается на другую работу, уходит на обед или в любой другой момент, когда перестаёт работать над этим объектом - выключает любой включенный (на экране отмеченный красным), или "свой номер". В этот момент на карту памяти записывается событие: время начала, время окончания, количество секунд сессии.
Данные с карты памяти легко импортируются в любой табличный редактор и анализируются.
Надо понимать, что данное изделие не обладает контрольно-надзорным функционалом и никак не защищено от злоупотреблений. Его задача избавить инженерный персонал от учётных процедур, а так же помогать в пересмотре норм на технические операции.
LabourLogger:
/*
Устройство для фиксации времени работы над объектом для 4х сотрудников
Состоит: нано 328, tft 240x320, модуль реального времени, кардридер, 4 тумблера, модуль питания
При включении любого тумблера начинается отсчёт времени работы для сотрудника. Время начала выводится на экран.
При выключении тумблера время окончания фиксируется на экране. Выводится количество секунд сессии.
На карту памяти записывается лог: сотрудник, дата, время начала сессии, время окончания сессии, количество секунд сессии.
Дальнейший анализ данных проводится путём импорта текстового файла в табличный редактор (Microsoft Excel, например).
*/
#include <microDS3231.h>
MicroDS3231 rtc;
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
#include <SD.h>
#define TFT_CS 10 //D10
#define TFT_RST 9 //D9
#define TFT_DC 8 //D8
#define TFT_MOSI 11 // D11
#define TFT_SCLK 13 // D13
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
#define black 0x0000
#define blue 0x001F
#define red 0xF800
#define green 0x07E0
#define cyan 0x07FF
#define magenta 0xF81F
#define yellow 0xFFE0
#define white 0xFFFF
#define maroon 0x7800
const int chipSelect = 7; //номер ноги для кардридера
int rab01[2][3]; //Массив данных о начале работы и окончании на каждого сотрудника 2х3 : начало-конец, час-минута-секунда
int rab02[2][3];
int rab03[2][3];
int rab04[2][3];
long sec01; // количество секунд работы каждой сессии для каждого сотрудника
long sec02;
long sec03;
long sec04;
bool fl01 = true; // флаги для однократного выполнения операций
bool fl02 = true;
bool fl03 = true;
bool fl04 = true;
String dataString = "";
void setup() {
tft.init(240, 320); // Init ST7789 320x240
tft.setRotation(1);
tft.fillScreen(0);
tft.setTextSize(2);
if (!SD.begin(chipSelect)) {
tft.println("Card failed, or not present");
while (1);
}
tft.println("Card initialized.");
delay(2000);
tft.fillScreen(0);
pinMode(2, INPUT_PULLUP); // ноги для тумблеров
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
tft.drawLine(0, 0, 319, 0, yellow); //сетка на экране
tft.drawLine(0, 59, 319, 59, yellow);
tft.drawLine(0, 119, 319, 119, yellow);
tft.drawLine(0, 179, 319, 179, yellow);
tft.drawLine(0, 239, 319, 239, yellow);
}
void loop() {
DateTime now = rtc.getTime();
/*
Замыкаем тумблеры на землю, поэтому невключенный тумблер выдаёт на ногу МК 1 (true).
Если тумблер включен и флаг выполнения true, тогда выполняем условие:
заполняем первую строку двустрочного массива данных значениями часов, минут и секунд из модуля реального времени;
синий фон (служит для "очистки" секции экрана); выводим время начала сессии; рисуем красный прямоугольник - как сигнал
идущего процесса. Переводим флаг в false, чтобы не выполнять больше это условие до окончания сессии.
*/
if (!digitalRead(2) and fl01) {
rab01[0][0] = now.hour;
rab01[0][1] = now.minute;
rab01[0][2] = now.second;
fl01 = false;
tft.fillRect(1, 1, 319, 58, blue);
tft.setTextSize(3);
tft.setCursor(5, 3);
tft.print(rtc.getTimeString());
tft.fillRect(2, 39, 72, 18, red);
tft.setTextSize(2);
tft.setCursor(80, 39);
tft.print("A&P #1:(sec) ");
}
if (!digitalRead(3) and fl02) {
rab02[0][0] = now.hour;
rab02[0][1] = now.minute;
rab02[0][2] = now.second;
fl02 = false;
tft.fillRect(0, 60, 319, 58, blue);
tft.setTextSize(3);
tft.setCursor(5, 62);
tft.print(rtc.getTimeString());
tft.fillRect(2, 98, 72, 18, red);
tft.setTextSize(2);
tft.setCursor(80, 98);
tft.print("A&P #2:(sec) ");
}
if (!digitalRead(4) and fl03) {
rab03[0][0] = now.hour;
rab03[0][1] = now.minute;
rab03[0][2] = now.second;
fl03 = false;
tft.fillRect(0, 120, 319, 58, blue);
tft.setTextSize(3);
tft.setCursor(5, 121);
tft.print(rtc.getTimeString());
tft.fillRect(2, 157, 72, 18, red);
tft.setTextSize(2);
tft.setCursor(80, 157);
tft.print("A&P #3:(sec) ");
}
if (!digitalRead(5) and fl04) {
rab04[0][0] = now.hour;
rab04[0][1] = now.minute;
rab04[0][2] = now.second;
fl04 = false;
tft.fillRect(0, 180, 319, 58, blue);
tft.setTextSize(3);
tft.setCursor(5, 180);
tft.print(rtc.getTimeString());
tft.fillRect(2, 216, 72, 18, red);
tft.setTextSize(2);
tft.setCursor(80, 216);
tft.print("A&P #4:(sec) ");
}
/*
При выключении тумблера (появления true на ноге МК) и флага в состоянии false выполняем условие:
заполняем вторую строку массива данных значениями часов, минут, секунд из модуля реального времени;
вычисляем количество секунд сессии; переводим флаг в состояние true, для возможности повторного запуска следующей сессии;
выводим на экран время окончания сессии, количество секунд сессии, рисуем зелёный прямоугольник - как сигнал завершённой сессии;
на карту памяти записываем сведения: сотрудник, время начала сессии, время окончания, количество секунд всех сессий, дата.
*/
if (digitalRead(2) and !fl01) {
rab01[1][0] = now.hour;
rab01[1][1] = now.minute;
rab01[1][2] = now.second;
sec01 = sec01 + (rab01[1][0] - rab01[0][0]) * 3600 + (rab01[1][1] - rab01[0][1]) * 60 + (rab01[1][2] - rab01[0][2]);
fl01 = true;
tft.setTextSize(3);
tft.setCursor(170, 3);
tft.print(rtc.getTimeString());
tft.fillRect(2, 39, 72, 18, green);
tft.setTextSize(2);
tft.setCursor(80, 39);
tft.print("A&P #1:(sec) ");
tft.print(sec01);
File dataFile = SD.open("datalog.txt", FILE_WRITE);
dataString = "A&P #1, " + String(rab01[0][0]) + ":" + String(rab01[0][1]) + ":" + String(rab01[0][2]) + "," + String(rab01[1][0]) + ":" + String(rab01[1][1]) + ":" + String(rab01[1][2]) + "," + String(sec01);
dataFile.println(dataString);
dataFile.close();
sec01 = 0;
}
if (digitalRead(3) and !fl02) {
rab02[1][0] = now.hour;
rab02[1][1] = now.minute;
rab02[1][2] = now.second;
sec02 = sec02 + (rab02[1][0] - rab02[0][0]) * 3600 + (rab02[1][1] - rab02[0][1]) * 60 + (rab02[1][2] - rab02[0][2]);
fl02 = true;
tft.setTextSize(3);
tft.setCursor(170, 62);
tft.print(rtc.getTimeString());
tft.fillRect(2, 98, 72, 18, green);
tft.setTextSize(2);
tft.setCursor(80, 98);
tft.print("A&P #2:(sec) ");
tft.print(sec02);
File dataFile = SD.open("datalog.txt", FILE_WRITE);
dataString = "A&P #2, " + String(rab02[0][0]) + ":" + String(rab02[0][1]) + ":" + String(rab02[0][2]) + "," + String(rab02[1][0]) + ":" + String(rab02[1][1]) + ":" + String(rab02[1][2]) + "," + String(sec02);
dataFile.println(dataString);
dataFile.close();
sec02 = 0;
}
if (digitalRead(4) and !fl03) {
rab03[1][0] = now.hour;
rab03[1][1] = now.minute;
rab03[1][2] = now.second;
sec03 = sec03 + (rab03[1][0] - rab03[0][0]) * 3600 + (rab03[1][1] - rab03[0][1]) * 60 + (rab03[1][2] - rab03[0][2]);
fl03 = true;
tft.setTextSize(3);
tft.setCursor(170, 121);
tft.print(rtc.getTimeString());
tft.fillRect(2, 157, 72, 18, green);
tft.setTextSize(2);
tft.setCursor(80, 157);
tft.print("A&P #3:(sec) ");
tft.print(sec03);
File dataFile = SD.open("datalog.txt", FILE_WRITE);
dataString = "A&P #3, " + String(rab03[0][0]) + ":" + String(rab03[0][1]) + ":" + String(rab03[0][2]) + "," + String(rab03[1][0]) + ":" + String(rab03[1][1]) + ":" + String(rab03[1][2]) + "," + String(sec03);
dataFile.println(dataString);
dataFile.close();
sec03 = 0;
}
if (digitalRead(5) and !fl04) {
rab04[1][0] = now.hour;
rab04[1][1] = now.minute;
rab04[1][2] = now.second;
sec04 = sec04 + (rab04[1][0] - rab04[0][0]) * 3600 + (rab04[1][1] - rab04[0][1]) * 60 + (rab04[1][2] - rab04[0][2]);
fl04 = true;
tft.setTextSize(3);
tft.setCursor(170, 180);
tft.print(rtc.getTimeString());
tft.fillRect(2, 216, 72, 18, green);
tft.setTextSize(2);
tft.setCursor(80, 216);
tft.print("A&P #4:(sec) ");
tft.print(sec04);
File dataFile = SD.open("datalog.txt", FILE_WRITE);
dataString = "A&P #4, " + String(rab04[0][0]) + ":" + String(rab04[0][1]) + ":" + String(rab04[0][2]) + "," + String(rab04[1][0]) + ":" + String(rab04[1][1]) + ":" + String(rab04[1][2]) + "," + String(sec04);
dataFile.println(dataString);
dataFile.close();
sec04 = 0;
}
delay(1000);
}
Вложения
-
56.5 KB Просмотры: 51