(Arduino) Is there a way to add a stopwatch to count how long the user has spent time using the program? - c++

Our project is a mp3 player, we're all beginners at coding. The project has a sort of a 'main menu' from which the user is able to choose from options such as: show track info, shuffle playlist, etc. Now we're trying to add a feature that tells the user how long they've been logged in. Our stopwatch code:
unsigned long timeListened = 0;
static int sknt1=0;
static int sknt10=0;
static int min1=0;
static int min10=0;
static int hour1=0;
static int hour10=0;
static int hour100=0;
void loop() {
timeListened = millis();
if (timeListened >= 1000) {
sknt1 = sknt1 + 1;
timeListened = 0;
}
if (sknt1 == 10) {
sknt10 = sknt10 + 1 ;
sknt1 = 0;
}
if (sknt10 == 6) {
min1 = min1 + 1;
sknt10 = 0;
}
if (min1 == 10) {
min10 = min10 + 1;
min1=0;
}
if (min10 == 6) {
hour1=houri1+1;
min10=0;
}
if (hour1 == 10){
hour10 = hour10 + 1;
hour10=0;
}
Serial.print (hour100);
Serial.print (hour10); Serial.print(hour1); Serial.print(":");
Serial.print(min10); Serial.print(min1); Serial.print(":");
Serial.print(sknt10); Serial.println(sknt1);
delay(1000);
}
The issue is, we can't find the right spot to place this code in. Only results we've had is either the stopwatch adds 1 second every time the user chooses the option from the menu, or the stopwatch time is just 000:00:00.
Is there a way to make arduino run the stopwatch in the background while the main program (playing music) is running ?

I have written a some code that prints the elapsed time since the Arduino was turned on for another project. It is not efficient, but it works.
You could call this every second in your loop() in order to update it.
#define second (1000L)
#define minute (60L*1000L)
#define hour (60L*60L*1000L)
unsigned long testTime = millis();
unsigned long hh = (testTime ) / hour;
unsigned long mm = ((testTime ) % hour) / minute ;
unsigned long ss = (((testTime ) % hour) % minute) / second;
Serial.print(hh);Serial.print(':');
Serial.print(mm);Serial.print(':');
Serial.print(ss);Serial.print('\n');

You are already using millis in your code which gives you the time in milliseconds ellapsed since the program started.
So whenever you want to know how long the program has been running just call millis().
This will overflow after approximately 50 days but that's probably irrelevant in your use case.
The problem with your code is that you add 1 second every time millis returns a value > 1000 which is always the case if your Arduino is running for more than 1 second.
This also has the effect that you only add 1 second every time you check that. Not every second.
There is also no need to delay your program to get an update every second.
Simply conver the return value of millis() to a time string. It gives you the milliseconds since program start. So calculate how many hours, minutes and seconds that is. I guess I don't have to tell you that 60000ms make a minute...
If you want to know the time passed since a certain event. For example a user login, you store the time of that event and calculate the difference to the current time.

Related

Arduino code- to do the same operation every minute

I am trying to run the following code. But I couldn't get the expected result. It is for an Arduino-based system. I need to run some Tests. Each test has two parameters. The number of 'Samples' and how long each sample to be tested. For example, if the s_count = 5 and t_count = 10, there are a total of 5 samples and each sample should be tested for 10 minutes. During this 10 minutes sample, I want to generate the result every minute and at the end, I calculate the average (of 10 minutes result). Following is my code. I ended up in an infinite loop inside the second while loop. Any suggestions, please.
unsigned long previousMillis = 0;
const long interval = 60000;
void startTest(int s_count, int t_count)
{
int sample_number = s_count;
int test_time = t_count;
while(sample_number > 0)
{
while(test_time >0)
{
unsigned long currentMillis = millis();
// do measurement every one minute
if (currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis;
doTest();
test_time--;
}
}
// reset the time counter after finishing one sample
test_time = t_count;
// go to the next sample
sample_number--;
}
}
Use the following code:
bool done=false;
if(done==false&&millis()%60000<100){
functions here
done=true;
}

problem with resetting window repeat clock at c++

problem with resetting window while repeat clock at c++
I tried to reset the time using time, chrono. However, the code execution time continued to increase without initialization.
Hello, I'm a student at the Korea Institute of Technology. Use the translator.
Please excuse me for speaking awkwardly.
I'm designing a program that uses the C++ OpenPose library to measure the right PC user tax.
Basically, we've completed the function of floating a pop-up to provide feedback when your right shoulder or left shoulder is crooked.
However, I would like to issue an alert after a certain second rather than a feedback that is sent in the wrong position.
Time should be measured when the supose function is not executed, but when the user is sitting in the wrong position. Time will be measured from the time when the supose function is executed. An event should occur if the same seat is held for 20 seconds from the wrong seat.
The event will occur after 20 seconds, and if the time is not initialized, it will occur as soon as it is recognized as an incorrect posture. I think it's because of when. If the library breaks from where, it ends with 0 code.
Once I've solved the time-related function, I'm going to ask you a question because I'm having a hard time completing the program.
Thank you.
while (!userWantsToExit)
{
// start frame
std::shared_ptr<std::vector<UserDatum>> datumProcessed;
if (opWrapper.waitAndPop(datumProcessed))
{
userWantsToExit = userOutputClass.display(datumProcessed);
userOutputClass.printKeypoints(datumProcessed);
....
//string to int
int subShoulder = stoi(rShoulderY) - stoi(lShoulderY);
//clac keypoint values for posedata
if (50 < subShoulder || -50 > subShoulder)
{
if (stoi(rShoulderY) < stoi(lShoulderY)) {
clock_t t_start, t_end;
int time;
t_start = clock(); //start clock
time = t_start / CLOCKS_PER_SEC;
op::log(time);
if (time > 20) {
t_end = clock(); //end clock
time = (int)(t_end - t_start) / CLOCKS_PER_SEC;
cv::imshow("SUPOSE", imgLshoulderDown);
std::string id = "hjw";
std::string pose = "leftShoulder";
httpRequestPose(id, pose);
}
}
else if (stoi(rShoulderY) > stoi(lShoulderY)) {
clock_t t_start, t_end;
int time;
t_start = clock(); //start clock
time = t_start / CLOCKS_PER_SEC;
op::log(time);
if (time > 20) {
cv::imshow("SUPOSE", imgRshoulderDown);
std::string id = "hjw";
std::string pose = "rightShoulder";
httpRequestPose(id, pose);
}
t_end = clock();
time = (int)(t_end - t_start) / CLOCKS_PER_SEC;
}
else {
clock_t t_start, t_end;
int time;
t_end = clock();
time = (int)(t_end - t_start) / CLOCKS_PER_SEC;
}
}
}
else {}
//op::log("Processed datum could not be emplaced.", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);
}
*image
Honestly, it is very hard for me to completely understand your question. However, I was a student and not good at english (even now), i know how struggling it was to find help with google translated paragraphs. Hence, i will make a try.
As I understand, you want to trigger an alert if the shoulder keeps inclining left for more than 20 seconds (same to right incline). Is that correct?
If it is correct, I think the problem is that you keep the variable t_start inside the poseDetect function. It means that everytime the pose is detected the t_start is a new one. The value (t_end - t_start) is always 0. You should declare t_start outside of that function and use a flag to check if it is the first time. I would like to suggest with below pseudo code
bool isLeftIncline = false;
clock_t startLeft=clock(); //get current time
void poseDetect()
{
if (50 < subShoulder || -50 > subShoulder){
if (stoi(rShoulderY) < stoi(lShoulderY)){ // should is inclined to the left
if(!isLeftIncline){ // the first time
startLeft=clock(); // get the starting time
isLeftIncline=true;
//trigger for the first time here
}else { // after the first time
clock_t current=clock();
int timeDiff=current-startLeft;
if(timeDiff>20){ //after 20 second with same pose
// issue an alert
}
//or trigger alert every nearly 20 seconds
//if(timeDiff%20<3){
//trigger
//}
}
}else {
// the shoulder no longer inclines to the left
// reset isLeftIncline time
isLeftIncline = false;
}
// you can apply the same for the right incline here
}
}

C++ Time adding + over time detection

Currently working on an assignment for a C++ class I'm taking. The goal of the project is to show military time accurately. Hours can range from 0-23 and minutes 0-59.
For the first part, I created a constructor that accepts a hour parameter and a optional minute parameter.
Here:
#include "stdafx.h"
#include<iostream>
#include<string>
using namespace std;
// Class Time
class time
{
private:
int hours, minutes;
public:
time(int, int = 0);
void displayTime();
void setTime(int);
};
// Max time possibilities
const int MAXMIN = 59;
const int MAXHOUR = 23;
// time constructor
time::time(int conHour, int conMin)
{
// Check for max hour limitations
if (conHour > MAXHOUR)
{
hours = MAXHOUR;
}
else
{
hours = conHour;
}
// Check for max minute limitation
if (conMin > MAXMIN)
{
minutes = MAXMIN;
}
else
{
minutes = conMin;
}
}
If the we place in anything higher than 23 for the hours or 59 for the minutes, it just sets them to the maximums 23, 59 respectively.
The next step was to add a "setTime" function where the user/sys can add minutes to the time (This is where the issue lies). If the minutes added would cause the minutes to go above 59, we add one to the hour. If the hour add causes the hours to go above 23, we reset it back to 0 and count up as needed.
currently I have the function:
// Set the time
void time::setTime(int newMin)
{
int addMin = newMin;
// Check for max minutes, if so add an hour
do
{
if (minutes + (addMin - MAXMIN) > MAXMIN)
{
addMin - MAXMIN;
if (hours + 1 > MAXHOUR)
{
hours = 0;
}
else
{
hours = hours + 1;
}
}
else
{
minutes += addMin;
}
} while (minutes + addMin > MAXMIN);
minutes += addMin;
I wrote the function where the loop would continuously check if the addMin amount would cause the minute to go above 59. The way I'm fairly sure I wrote it was to check if the minutes +(addMin-MAXMIN) is greater than the MAXMIN, if it is, subtract 59 and then add an hour. That is where the hour check comes in and checks if the hour would go above 23, if so reset it. The idea is that it would keep looping through until we have a set time. However, when running the program, it stalls out. This leads me to believe I have an infinite loop somewhere, but I cannot identify it.
Here is my main function:
int main()
{
time aTime(50,15);
aTime.displayTime();
aTime.setTime(100);
aTime.displayTime();
// Pause before we exit
system("pause.exe");
return 0;
}
the line addMin - MAXMIN did not do anything as I hadn't included addMIN = addMin - MAXMIN the variable was not getting updated on each iteration.
Credits to #immibis

Is this a good way to lock a loop on 60 loops per second?

I have a game with Bullet Physics as the physics engine, the game is online multiplayer so I though to try the Source Engine approach to deal with physics sync over the net. So in the client I use GLFW so the fps limit is working there by default. (At least I think it's because GLFW). But in the server side there is no graphics libraries so I need to "lock" the loop which simulating the world and stepping the physics engine to 60 "ticks" per second.
Is this the right way to lock a loop to run 60 times a second? (A.K.A 60 "fps").
void World::Run()
{
m_IsRunning = true;
long limit = (1 / 60.0f) * 1000;
long previous = milliseconds_now();
while (m_IsRunning)
{
long start = milliseconds_now();
long deltaTime = start - previous;
previous = start;
std::cout << m_Objects[0]->GetObjectState().position[1] << std::endl;
m_DynamicsWorld->stepSimulation(1 / 60.0f, 10);
long end = milliseconds_now();
long dt = end - start;
if (dt < limit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(limit - dt));
}
}
}
Is it ok to use std::thread for this task?
Is this way is efficient enough?
Will the physics simulation will be steped 60 times a second?
P.S
The milliseconds_now() looks like this:
long long milliseconds_now()
{
static LARGE_INTEGER s_frequency;
static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
if (s_use_qpc) {
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (1000LL * now.QuadPart) / s_frequency.QuadPart;
}
else {
return GetTickCount();
}
}
Taken from: https://gamedev.stackexchange.com/questions/26759/best-way-to-get-elapsed-time-in-miliseconds-in-windows
If you want to limit the rendering to a maximum FPS of 60, it is very simple :
Each frame, just check if the game is running too fast, if so just wait, for example:
while ( timeLimitedLoop )
{
float framedelta = ( timeNow - timeLast )
timeLast = timeNow;
for each ( ObjectOrCalculation myObjectOrCalculation in allItemsToProcess )
{
myObjectOrCalculation->processThisIn60thOfSecond(framedelta);
}
render(); // if display needed
}
Please note that if vertical sync is enabled, rendering will already be limited to the frequency of your vertical refresh, perhaps 50 or 60 Hz).
If, however, you wish the logic locked at 60fps, that's different matter: you will have to segregate your display and logic code in such a way that the logic runs at a maximum of 60 fps, and modify the code so that you can have a fixed time-interval loop and a variable time-interval loop (as above). Good sources to look at are "fixed timestep" and "variable timestep" ( Link 1 Link 2 and the old trusty Google search).
Note on your code:
Because you are using a sleep for the whole duration of the 1/60th of a second - already elapsed time you can miss the correct timing easily, change the sleep to a loop running as follows:
instead of
if (dt < limit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(limit - dt));
}
change to
while(dt < limit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(limit - (dt/10.0)));
// or 100.0 or whatever fine-grained step you desire
}
Hope this helps, however let me know if you need more info:)

Check system time in MFC Dialog Application 24/7

I am trying to make my program check for the system time 24/7 in a loop in a mfc dialog application.
a little background on what i did so far.
My GUI has a few buttons:- start, stop, exit, and a few edit boxes to show values.
It is meant to read into a .txt file at a predetermined location 24/7 at a specified interval time by the user. This could be 5 mins to however long the user wants, but it has to be in multiples of 5. For example, 5 min, 10 min, 15 min, 20 min so on and so forth.
After reading the .txt file, it will then compare the strings within the .txt file and output to a .csv file.
Thats the brief explanation on what I am trying to do. Now on to the question at hand.
Since I need the program to run 24/7, I am trying to make the program check the system time consistently and trigger a set of functions when the interval time specified by the user has been reached.
For that, I made a variable whenever the start button is pressed
BOOL start_flag = true;
and the start_flag will only return to false once the stop button is pressed
and then I had it in a while loop
while (start_flag)
{
Timer(); // To add the user entered interval time to current time
Timer_Secondary(); // To compare the converted time against the current time
Read_Log(); // Read the logs
}
///////////////////Timer function//////////////////////
{
CTime curTime = CTime::GetCurrentTime();
timeString_Hour = curTime.Format("%H");
timeString_Minute = curTime.Format("%M");
timeString_Second = curTime.Format("%S");
Hour = atoi(timeString_Hour);
Minute = atoi(timeString_Minute);
Second = atoi(timeString_Second);
if ((first_run == false) && (Int_Frequency < 60))
{
int Minute_Add = Minute + Int_Frequency;
if (Minute_Add >= 60)
{
Minute_Add = Minute_Add - 60;
Hour = Hour + 1;
}
Minute = Minute_Add;
}
if ((first_run == false) && (Int_Frequency >= 60))
{
int Local_Frequency = Int_Frequency;
while (Local_Frequency >= 60)
{
Local_Frequency = Local_Frequency - 60;
Hour = Hour + 1;
}
}
if (first_run)
{
Hour = Hour + 1;
Minute = 00;
Second = 00;
first_run = false;
}
timeString_Hour.Format("%d", Hour);
timeString_Minute.Format("%d", Minute);
timeString_Second.Format("%d", Second);
}
////////Timer_Secondary function//////////
{
CTime curTime = CTime::GetCurrentTime();
timeString_Hour_Secondary = curTime.Format("%H");
timeString_Minute_Secondary = curTime.Format("%M");
timeString_Second_Secondary = curTime.Format("%S");
Hour_Secondary = atoi(timeString_Hour);
Minute_Secondary = atoi(timeString_Minute);
Second_Secondary = atoi(timeString_Second);
}
Right, the problem i have so far is that because of the while loop, the program is stuck in an infinite loop and the GUI freezes due to that and the user wont be able to make it stop.
There are a few things i thought in my head but am not sure if it will work.
while (start_flag)
{
if((Hour_Secondary == Hour) && (Minute_Secondary == Minute) && (Second_Secondary == Second))
{
// Run parsing function in this (main bit of code)
start_flag = false; //Set it to false so it will jump back out of this loop
}
if ((Hour_Secondary != Hour) && (Minute_Secondary != Minute) && (Second_Secondary != Second))
{
// Some form of time function in this to wait every 1 min then loop back to start of while loop)
// With the timer function, the GUI should be usable at this point of time
}
}
Any advice would be much appreciated. I hope this post wasnt too confusing in its layout as I wanted to provide as much as I can to show that I am not just asking questions without trying to fix it myself first.
Whilst you are in your while loop, the windows message pump is not processing, ergo - your user interface freezes up. You have 2 options, as I see it:
1) Use a background thread to do this.
2) Investigate CWnd::SetTimer and use that to perform the timings. This will post a message in to the message queue at the intervals you specify (It's not a real-time solution, but I don't think you have that requirement), and therefore your interface will remain alive.
Add timer control in your dialog and handle WM_TIMER message.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644901(v=vs.85).aspx#creating_timer