I'm a beginner program and trying to create a "Simon" memory game using Processing. I'm currently using a timer to display a new object every second. However, I cannot determine how to make the object disappear shortly after it is displayed (e.g., half a second after it appears). I've tried creating a second timer object that redraws the background after a certain amount of time, but it's just not working. Any help is greatly appreciated!!
int j = 0;
void draw() {
if (displayTimer.isFinished()){
hideTimer.start();
if(hideTimer.isFinished()){
drawBackground();
}
if (nomisSequence[j] == color(255, 0, 0)) {
drawBackground();
button1.display();
}
else if (nomisSequence[j] == color(0, 255, 0)) {
drawBackground();
button2.display();
}
else if (nomisSequence[j] == color(0, 0, 255)) {
drawBackground();
button3.display();
}
else if (nomisSequence[j] == color(255, 255, 0)) {
drawBackground();
button4.display();
}
if(hideTimer.isFinished()){
drawBackground();
}
j++;
displayTimer.start();
hideTimer.start();
}
}
I don't know what timer objects you're using, but you don't need them. Processing has a handy millis() function that you can use.
Just record the start time of any event you want to time, and then check whether that start time plus a duration is less than the current time.
Something like this:
int startMillis;
int duration = 1000;
void draw() {
background(0);
if (mousePressed) {
startMillis = millis();
}
if (millis() < startMillis + duration) {
ellipse(mouseX, mouseY, 10, 10);
}
}
Related
To simplify the problem as much as possible, I have two functions, a parent that calls the child. Everything executes okay till it gets to the return of the child function. After that I get a Bus Error.
int main () {
game();
// this doesn't get executed and program fails with bus error
printf("Execute 2");
return 1;
}
int game () {
game_t GameInfo = {.level = 1, .score = 0, .playerCh = 0, .playerX = 1, .playerY = 1};
gameLevel(&GameInfo);
mvprintw(1,1, "Executed");
// code works up to here and get's executed properly
return 1;
};
void gameLevel (game_t *GameInfo) {
// determine the size of the game field
int cellCols = COLS / 3;
int cellRows = (LINES / 3) - 2;
GameInfo -> playerX = 1;
GameInfo -> playerY = 1;
generateMaze(0);
int solved = 0;
int level = GameInfo -> level;
// default player position
getPlayerDefault(GameInfo);
pthread_t enemies_th;
pthread_create(&enemies_th, NULL, enemies, (void *)GameInfo);
// enemies(&level);
while (solved == 0 && GameInfo -> collision != 1) {
printGameInfo(GameInfo);
noecho();
char move = getch();
echo();
if (GameInfo -> collision != 1) {
if (checkMoveValidity(move, GameInfo) == 1) {
solved = movePlayer(move, GameInfo);
if (solved == 1) {
break;
}
}
} else {
break;
}
}
if (solved == 1) {
pthread_cancel(enemies_th);
GameInfo->level++;
gameLevel(GameInfo);
} else {
// game over
pthread_cancel(enemies_th);
return;
}
}
Now, the code is much more complicated than here, but I think that shouldn't have any influence on this (?) as it executes properly, until the return statement. There is also ncurses and multithreading, quite complex custom structures, but it all works, up until that point. Any ideas ?
Tried putting print statements after each segment of code, everything worked up until this.
pthread_cancel() doesn't terminate the requested thread immediately. The only way to know that a cancelled thread has terminated is to call pthread_join(). If the thread is left running, it will interfere with use of the GameInfo variable in the next level of the game if the current level is solved, or may use the GameInfo variable beyond its lifetime if the current level was not solved and the main thread returns back to the main() function.
To make sure the old enemies thread has terminated, add calls to pthread_join() to the gameLevel() function as shown below:
if (solved == 1) {
pthread_cancel(enemies_th);
pthread_join(enemies_th);
GameInfo->level++;
gameLevel(GameInfo);
} else {
// game over
pthread_cancel(enemies_th);
pthread_join(enemies_th);
return;
}
The use of tail recursion in gameLevel() seems unnecessary. I recommend returning the solved value and letting the game() function start the next level:
In game():
while (gameLevel(&GameInfo)) {
GameInfo.level++;
}
In gameLevel():
int gameLevel(game_t *GameInfo) {
/* ... */
pthread_cancel(enemies_th);
pthread_join(enemies_th);
return solved;
}
I am looking at using the Windows Threading API and the issue it seems to have is you cannot keep track of when all the threads are completed. You can keep track of when the work item has been completed, assuming you kept track of each one. From my research there is no direct way to query the thread pool to see if the work items submitted has all be completed.
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
VOID CALLBACK MyWorkCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WORK Work) {
DWORD threadId = GetCurrentThreadId();
BOOL bRet = FALSE;
printf("%d thread\n", threadId);
return;
}
int main() {
TP_CALLBACK_ENVIRON CallBackEnviron;
PTP_POOL pool = NULL;
PTP_CLEANUP_GROUP cleanupgroup = NULL;
PTP_WORK_CALLBACK workcallback = MyWorkCallback;
PTP_TIMER timer = NULL;
PTP_WORK work = NULL;
InitializeThreadpoolEnvironment(&CallBackEnviron);
pool = CreateThreadpool(NULL);
SetThreadpoolThreadMaximum(pool, 1);
SetThreadpoolThreadMinimum(pool, 3);
SetThreadpoolCallbackPool(&CallBackEnviron, pool);
for (int i = 0; i < 10; ++i) {
work = CreateThreadpoolWork(workcallback, NULL, &CallBackEnviron);
SubmitThreadpoolWork(work);
WaitForThreadpoolWorkCallbacks(work, FALSE); // This waits for the work item to get completed.
}
return 1;
}
Here is a simple example. What happens is on the WaitForThreadpoolWorkCallbacks I am able to wait on that specific work item. Which is no problem if I am doing a few things. However, if I am traversing a directory and have thousands of files that I need to have work done on them, I don't want to keep track of each individual work item. Is it possible to query the Thread Pool queue to see if anything is left for processing? Or to find out if any of the threads are still working?
you need keep track of active tasks ( like pendcnt in comment) +1. but this must not be global variable, but member in some struct. and pass pointer to this struct to work item. increment this counter before call SubmitThreadpoolWork and decrement from callback, before exit. but you also need and event - set this event in signal state, when counter became 0. and wait on event from main thread. if your code inside dll, which can be unloaded - you need also reference dll, before SubmitThreadpoolWork and FreeLibraryWhenCallbackReturns from callback. also important that counter value - was 1 (not 0) ininitally - so this is count_of_active_cb + 1, and decrement it before begin wait (if not do this - counter can became 0 early - for instance first callback exit before you activate second)
class Task
{
HANDLE _hEvent = 0;
ULONG _dwThreadId = 0;
LONG _dwRefCount = 1;
public:
~Task()
{
if (_hEvent) CloseHandle(_hEvent);
}
ULONG Init()
{
if (HANDLE hEvent = CreateEvent(0, 0, 0, 0))
{
_hEvent = hEvent;
return NOERROR;
}
return GetLastError();
}
void AddTask()
{
InterlockedIncrementNoFence(&_dwRefCount);
}
void EndTask()
{
if (!InterlockedDecrement(&_dwRefCount))
{
if (_dwThreadId != GetCurrentThreadId())
{
if (!SetEvent(_hEvent)) __debugbreak();
}
}
}
void Wait()
{
_dwThreadId = GetCurrentThreadId();
EndTask();
if (_dwRefCount && WaitForSingleObject(_hEvent, INFINITE) != WAIT_OBJECT_0) __debugbreak();
}
};
VOID CALLBACK MyWorkCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WORK /*Work*/)
{
// need only if your code in dll which can be unloaded
FreeLibraryWhenCallbackReturns(Instance, (HMODULE)&__ImageBase);
WCHAR sz[32];
swprintf_s(sz, _countof(sz), L"[%x] thread", GetCurrentThreadId());
MessageBoxW(0, 0, sz, MB_ICONINFORMATION);
reinterpret_cast<Task*>(Parameter)->EndTask();
}
void CbDemo()
{
Task task;
if (task.Init() == NOERROR)
{
ULONG n = 2;
do
{
if (PTP_WORK pwk = CreateThreadpoolWork(MyWorkCallback, &task, 0))
{
HMODULE hmod;
// need only if your code in dll which can be unloaded
if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (PWSTR)&__ImageBase, &hmod))
{
task.AddTask();
SubmitThreadpoolWork(pwk);
}
CloseThreadpoolWork(pwk);
}
} while (--n);
MessageBoxW(0, 0, L"Main Thread", MB_ICONWARNING);
task.Wait();
__nop();
}
}
For a aspberry pi project I have buttons connected to GPIO and I want to take different actions depending on how long a button has been pressed. The following python code (extract) is working as expected:
on_button2(channel):
t1 = time.time()
# Wait for button release
while GPIO.input(channel) == 0:
pass
duration = time.time() - t1
print "duration: %f" % (duration)
if duration > 0.75:
mpd_client.previous()
else:
mpd_client.next()
GPIO.add_event_detect(BUTTON2_PIN, GPIO.FALLING, callback=on_button2, bouncetime=700);
I would like to convert this into a C program (don't ask why, I really don't like python and I'm much more familiar with C, so I'd like to do it in C)
Trying to convert this to C with wiringPi, I came up with this, but it is not working as expected:
unsigned long btn2_t0;
static void on_button_2_pressed() {
unsigned long duration, t1;
int level;
level = digitalRead(BUTTON_2_PIN);
// Debounce button
t1 = millis();
if (t1 - btn2_t0 < 700) {
return;
}
btn2_t0 = t1;
// Wait for button being released
while (digitalRead(BUTTON_2_PIN) == LOW) {
delay(100);
}
duration = millis() - t1;
if (duration > 5000) {
printf("Self destruction sequence initiated!\n");
}
else if (duration > 700) {
player_previous();
}
else {
player_next();
}
}
int main() {
// Setup WiringPi Lib
wiringPiSetupGpio();
pinMode(BUTTON_2_PIN, INPUT);
// Register callbacks on button press
wiringPiISR(BUTTON_2_PIN, INT_EDGE_FALLING, on_button_2_pressed);
for (;;) {
delay(500);
}
return 0;
}
It seems that the loop that should wait for button release is not being executed or that the while-condition is always true, and thus, duration always is zero.
Is the digitalRead(BUTTON_2_PIN) function equivalent to the GPIO.input(channel) in the python code at all?
If somebody could point me in the right direction on how to detect button press (software-debounced) and measure the duration of the button press in C.
Thanks a lot.
EDIT: Working solution
After playing around a lot and with the help of Francesco Boi I came around with a working solution, although I do not really understand why the compare logic with HIGH / LOW is swapped compared to the python code (I thought that the button press will cause the pin to FALL to LOW and releasing it would RAISE it to HIGH ...)
static void on_button_2_pressed() {
unsigned long duration;
static unsigned long button_pressed_timestamp;
int level = digitalRead(BUTTON_2_PIN);
if (level == HIGH) { // Why HIGH ?!?
button_pressed_timestamp = millis();
}
else {
duration = millis() - button_pressed_timestamp;
button_pressed_timestamp = millis();
if (duration < 100) {
// debounce...
return;
}
else if (duration < 700) {
syslog(LOG_NOTICE, ">> NEXT\n");
}
else if (duration < 3000) {
syslog(LOG_NOTICE, "<< PREV\n");
}
else {
syslog(LOG_NOTICE, "!! REBOOT\n");
}
}
}
int main() {
...
wiringPiISR(BUTTON_2_PIN, INT_EDGE_BOTH, on_button_2_pressed);
...
}
First of all you are reading the value of the pin into level then in the while loop you are re-reading it: why is that? Can't you do something like:
// Wait for button being released
while (level == LOW) {
delay(100);
}
?
Also don't you want to reassign the btn2_t0 = t1; even when the time was smaller than 700 ms? Like:
t1 = millis();
if (t1 - btn2_t0 < 700) {
btn2_t0 = t1;
return;
}
The behaviour depends on how you built your electronic circuit: is the button-press suppose to make the pin high or low? Be sure about the behaviour is the one you are expecting by either connecting a led and a resistor or using a Voltmeter.
However since your Python code worked I am assuming the electronic is correct and your algorithm too.
Be sure of course you are pressing the button long enough. Add some prints to your code to understand which branches it is executing because when there is electronic involved it is difficult to understand only by the code.
While waiting for news from you, in my opinion is better to do the following: define the callback as: INT_EDGE_BOTH so that it got called when the bottom is pressed and when the button is released. You can keep the time elapsed with a static variable.
void yourCallback()
{
unsigned long ela, t;
int level = digitalRead(BUTTON_2_PIN);
static unsigned long button_pressed_timestamp;
//if button pressed:
if(level==LOW)
{
//start counting
button_pressed_timestamp = millis();
}
else //button released
{
duration = millis()-button_pressed_timestamp;
button_pressed_timestamp = millis(); //just to be sure....
if (duration > 5000) {
printf("Self destruction sequence initiated!\n");
}
else if (duration > 700) {
player_previous();
}
else {
player_next();
}
}
}
Briefly: I would like to turn on a relay for 30 seconds, after I toggle a switch on.
I'm trying to do a blinds automation at home.
I have a simple ON-OFF-ON switch, attached to an Arduino connected to Relays.
I want to turn on Relay#1 for a maximum of 30 seconds if I toggle the switch down from center. In other words, relay turns on when I switch, and when timer reaches 30 seconds relay turns off.
similarly I want to turn on Relay#2 for exactly 30 seconds if I toggle the switch up from center
And when I switch back to center, I would like the timer to reset.
I could not figure out how. Could anyone help?
I have been trying to use elapsedMillis library for this, which is a nice library that helps me avoid using Delays:
http://playground.arduino.cc/Code/ElapsedMillis
However even though I could work the relays without the 30 second limitation, I couldn't figure out the code to end working of the relays. Here is my current code:
#include <elapsedMillis.h>
#define RELAY_ON 0
#define RELAY_OFF 1
#define RELAY1_TURNS_ON_BLINDS 5
#define RELAY2_SHUTS_DOWN_BLINDS 6
#define shutswitch A0
#define openswitch A1
bool LocalCommandToOpen;
bool LocalCommandToShut;
void setup() ////////SETUP////////
{
digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_OFF);
digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_OFF);
pinMode(RELAY1_TURNS_ON_BLINDS, OUTPUT);
pinMode(RELAY2_SHUTS_DOWN_BLINDS, OUTPUT);
pinMode(shutswitch, INPUT);
pinMode(openswitch, INPUT);
} ////SETUP
void loop() { ///////LOOP
if (digitalRead(shutswitch) == 1)
{
LocalCommandToOpen = 1;
}
else
{
LocalCommandToOpen = 0;
}
if ( digitalRead(openswitch) == 1)
{
LocalCommandToShut = 1;
}
else
{
LocalCommandToShut = 0;
}
unsigned int CloseInterval = 14000;
elapsedMillis timeElapsedSinceCloseButtonPush = 0;
unsigned int OpenInterval = 14000;
elapsedMillis timeElapsedSinceOpenButtonPush = 0;
//MANUAL SWITCH OPERATION
if ( LocalCommandToShut == 1 )
{
digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_OFF);
digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_ON);
}
else
{
digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_OFF);
}
//MANUEL DUGME ILE ACMA
if ( LocalCommandToOpen == 1)
{
digitalWrite(RELAY2_SHUTS_DOWN_BLINDS, RELAY_OFF);
digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_ON);
}
else
{
digitalWrite(RELAY1_TURNS_ON_BLINDS, RELAY_OFF);
}
delay(500);
} /////////////////LOOP////////////////////////////////////
One suggestion here is to use a "state machine", so that upon a switch transition, you get 'State 1'; in that state, a timer starts, and puts you in 'State 2'. In 'State 2', you check the time, and if it goes beyond X seconds, you go to 'State 3'. You can monitor the transition of a switch from low to high (or high to low), and use this to reset the state of the system.
A sample bit of code gives you an idea of how to implement this. The variable 'SystemState' is an integer, and SYSTEM_ABORT, SYSTEM_IDLE, etc. are constants.
The beauty of this is that the transition is easy to figure out. For example, if you are in the SYSTEM_WAIT state, the only thing you are looking for is the time to be greater than 5 seconds. Also, you can look at input transitions or values to set states (like SystemStopButton == 0, to set the state to be 'SYSTEM_ABORT').
// SystemStopButton is an input
void SystemStateMachine(void)
///////////////////////////////////////////////////////////////////////////////////////////
{
if (SystemStopButton == 0)
{
SystemState = SYSTEM_ABORT;
}
switch (SystemState)
{
case SYSTEM_IDLE:
{
RunPinState = OFF;
StopPinState = OFF;
if (SystemRunButton == 0)
{
SystemState = SYSTEM_START;
ShowStep();
}
break;
}
case SYSTEM_START:
{
StandardMessage = "START ";
RunPinState = ON;
StopPinState = OFF;
SystemState = SYSTEM_WAIT;
ShowStep();
break;
}
case SYSTEM_WAIT: // wait for 5 seconds
{
StandardMessage = "WAIT ";
if ((CurrentMillis - StateStepTimeMillis) > 5000)
{
SystemState = SYSTEM_RETRACT;
ShowStep();
}
break;
}
case SYSTEM_RETRACT: //
{
StandardMessage = "RETRACT";
/* motor stuff goes here... */
if ((CurrentMillis - StateStepTimeMillis) > 5000)
{
SystemState = SYSTEM_ADVANCE_TAPE_WAIT
ShowStep();
}
break;
}
// etc. etc. etc.
case SYSTEM_ABORT: //
{
StandardMessage = "ABORT";
/* motor stop stuff goes here... */
SystemState=SYSTEM_IDLE;
break;
}
default:
{
break;
}
}
}
void ShowStep(void)
/////////////////////////////////////////////////////////////////////
// show step and set time so we can keep track of time in each step
{
Serial.print("SystemState = ");
Serial.println(String(SystemState));
SetStepTime();
}
void SetStepTime(void)
/////////////////////////////////////////////////////////////////////
{
StateStepTimeMillis = CurrentMillis;
}
You might use a state machine; this makes things a bit easier to follow.
Similar to:
Arduino Switch to Turn a Relay timer
A nice discussion of state machines is here:
Complicated state transitions: best practices
i am programming my differential drive mobile robot (e-puck) to move to a certain coordinate with specific orientation. the robot has no problem reaching the coordinate, however when it reaches the coordinate, it cannot settle on the specific orientation and keeping "spinning" on the spot searching for the orientation, do anyone have any prior experience in this? i am stuck in this issue for very long and really hope someone knows why. the relevant part of the code is pasted below.
static void step() {
if (wb_robot_step(TIME_STEP)==-1) {
wb_robot_cleanup();
exit(EXIT_SUCCESS);
}
}
.
.
.
.
.
static void set_speed(int l, int r)
{
speed[LEFT] = l;
speed[RIGHT] = r;
if (pspeed[LEFT] != speed[LEFT] || pspeed[RIGHT] != speed[RIGHT]) {
wb_differential_wheels_set_speed(speed[LEFT], speed[RIGHT]);
}
}
.
.
.
.
static void goto_position1(float x, float y, float theta)
{
if (VERBOSE > 0) printf("Going to (%f, %f, %f)\n",x,y,theta);
// Set a target position
odometry_goto_set_goal(&og, x, y, theta);
// Move until the robot is close enough to the target position
while (og.result.atgoal == 0) {
// Update position and calculate new speeds
odometry_track_step(og.track);
odometry_goto_step(&og);
// Set the wheel speed
set_speed(og.result.speed_left, og.result.speed_right);
printf("%f",ot.result.theta);
print_position();
step();
} //after exiting while loop speed will be zero
og.result.speed_left = 0;
og.result.speed_right = 0;
if (((og.result.speed_left == 0) && (og.result.speed_right == 0)) )
og.result.atgoal = 1;
return;
}
.
.
.
int main(){
//initialisation
while (wb_robot_step(TIME_STEP) != -1) {
goto_position1(0.0000000001,0.00000000001,PI/4);
}
return 0;
}
I do not have the benefit of knowing what the contents of your og struct are, so assuming there are members that provide current position information, (I will assume they are posx & posy), you should should have a test statement sometime just after having read the latest position, something like this:
[EDIT] re-positioned set_speed()
while (og.result.atgoal == 0)
{
// Update position and calculate new speeds
odometry_track_step(og.track);
odometry_goto_step(&og);
if(((og.result.posx - x) > 3) || (og.result.posy - y) > 3) //(distance assumed in mm)
{
//then report position, continue to make adjustments and navigate
printf("%f",ot.result.theta);
print_position();
// Set the wheel speed
set_speed(og.result.speed_left, og.result.speed_right);
step();
}
else
{
//set all speeds to 0
//report position.
//clear appropriate struct members and leave loop
}
} //after exiting while loop speed will be zero
i finally figured out what is wrong, it is because i could not get out of the while loop and the robot cannot stop searching for the orientation. Thanks for the inspiration.