IR Phototransistor Timer - timer

So im using two IR phototransistors paired with an infrared LED to calculate velocity by timing the time between when the first transistor is signaled and the second is signaled. The code works except for the part with the IR transistors. My original code used buttons as a tester just to see if the code worked but now I'm ready to move onto the actual IR receivers. My problem is the while loop that waits for the first transistor to be triggered is not repeatedly checking if the boolean logic is true, it only checks it once before moving onto the next bit of code or doing the while loop.
Heres the code in question
int IR1 = 0
int IR2 = 1
val = analogRead(IR1);
val2 = analogRead(IR2);
high = val > 330;
low = val < 330;
high2 = val2 > 330;
low2 = val2 < 330;
while(val == low) {} // waiting for button to be pushed
//begin Timer
//Display on LCD
lcd.clear();
lcd.print("Timing"); //print on LCD
startTime = millis(); //define startTime for calculation
while(val2 == high){} //wait until second button is pressed
// it went low - capture time
endTime = millis(); //define elapsedTime
elapsedTime = endTime - startTime; //deyfine elapsedTime for velocit
//velocity calculation
velocity = distance/(elapsedTime/1000);
I know the code is messy, but look at the first while loop because I can't figure out why it's not working

Related

C running script after given time frame while the game is still playable (not delay)

I'm learning C language and very new to this. I'm trying to write a simple game that spawns an enemy after 3 secs from the start of the level. I tried clock() function and had the problem that while it spawns after given time it also freezes the game so it is unplayable.
void delay (clock_t n) {
clock_t start = clock();
while(clock() - start < n);
}
Also tried the get_current_time() method but the game freezes if I got to this level so my code must be wrong. Can anyone give me some solution on how to approach this?
void draw_hero( void ) {
char * hero_image =
/**/ "H H"
/**/ "H H"
/**/ "HHHHH"
/**/ "H H"
/**/ "H H";
int hero_x = (screen_width() - HERO_WIDTH) / 2;
int hero_y = (screen_height() - HERO_HEIGHT) / 2;
hero = sprite_create(x, y, HERO_WIDTH, HERO_HEIGHT, hero_image);
double lastTime = get_current_time();
while (true){
double current = get_current_time();
double elapsed = current - lastTime;
//lastTime = current;
while (elapsed < lastTime + 500) ???
sprite_draw(hero);
show_screen();
}
clock is not the correct function to use. Nor is spinning in a tight loop to "sleep" appropriate.
Here's a minimal game loop based on your code and it demonstrates how to create the enemy thing at 3 seconds into it. But a real game is a bit more complicated...
I'm using "true", which is technically a C++ concept, but since you were using it in your own code, I suspect some C compilers will allow it.
I don't know what get_current_time is, but I assume it returns value with more granularity that a second (e.g. millisecond resolution).
// initialize - create screen, spawn initial sprites, create map etc..
bool has_created_enemy = false;
double baseTime = get_current_time(); // used for normalizing time to 0
double lastTime = 0; // last timestamp of last frame
double currentTime = 0; // timestamp of current frame
while (true)
{
lastTime = currentTime;
currentTime = get_current_time() - baseTime;
double elapsed_since_last_frame = currentTime - lastTime;
// keyboard input
// collision detection
// update game state
if ((currentTime >= 3.0) && (!has_created_enemy))
{
// spawn enemy
has_created_enemy = true;
}
// draw frame
}

Issue with framerate limiter (inaccurate)

The framerate limiter for this game I'm doing some coding on is having some pretty irritating accuracy issues at certain framerates. I've been scratching my head trying to think of a better way to write this, but the best I've came up with is still fairly inaccurate. I was wondering if someone could give me a couple ideas on how to rewrite this short portion to be more accurate.
//g_dwLastfps & currenttime are equal to timeGetTime()
float fFrameLimit = 0;
if (g_nFrameLimitValue > 0) //g_nFrameLimitValue = user defined
fFrameLimit = 1000 / g_nFrameLimitValue;
while ((currentTime - g_dwLastTime) < fFrameLimit)
{
// -1 = wait an extra ms. seemed to help accuracy some
Sleep((float)fFrameLimit - ((currentTime - g_dwLastTime)) - 1);
currentTime = timeGetTime();
}
g_dwLastTime = currentTime;
I can think of a pretty simple solution:
uint64_t last_time = 0;
uint64_t current_time = time();
uint64_t frame_limit_ms = 17; // 60fps = 16.666... ms/f
uint64_t frame_diff = frame_limit_ms;
sleep(frame_limit_ms);
while(running){
last_time = current_time;
current_time = time(); // get frame start time in milliseconds
frame_diff = current_time - last_time; // get time since last frame in ms
if(frame_diff < frame_ms_limit){
sleep(frame_ms_limit - frame_diff);
// need to do a re-calculation for accuracy
current_time = time();
frame_diff = current_time - last_time;
}
do_physics(frame_diff);
draw_scene();
swap_buffers();
}
Which looks a lot like what you have, but doesn't use float so should be faster and is accurate up to one unit of time (milliseconds in this case).
If you want it to be more accurate, use a more accurate unit (nanoseconds) and convert it back to milliseconds if you need to.
One issue with the example code, is that last_time get updated to current_time which gets updated to time(), which can lead to drift over time. To avoid this, last_time should be based on an original reading of time(), and advanced by the desired delay for each frame. The following windows based code is similar what is used in games to keep a thread running at a fixed frequency with no drift. uRem is used to deal with frequencies that aren't exact multiples of the clock frequency. dwLateStep is a debugging aid that gets incremented each instance where the step time is exceeded. The code is Windows XP compatible, where a Sleep(1) can take up to 2 ms, so it checks for >= 2 ms delay pending before using Sleep(1).
/* code for a thread to run at fixed frequency */
typedef unsigned long long UI64; /* unsigned 64 bit int */
#define FREQ 400 /* frequency */
DWORD dwLateStep; /* late step count */
LARGE_INTEGER liPerfFreq; /* 64 bit frequency */
LARGE_INTEGER liPerfTemp; /* used for query */
UI64 uFreq = FREQ; /* process frequency */
UI64 uOrig; /* original tick */
UI64 uWait; /* tick rate / freq */
UI64 uRem = 0; /* tick rate % freq */
UI64 uPrev; /* previous tick based on original tick */
UI64 uDelta; /* current tick - previous */
UI64 u2ms; /* 2ms of ticks */
UI64 i;
/* ... */ /* wait for some event to start thread */
QueryPerformanceFrequency(&liPerfFreq);
u2ms = ((UI64)(liPerfFreq.QuadPart)+499) / ((UI64)500);
timeBeginPeriod(1); /* set period to 1ms */
Sleep(128); /* wait for it to stabilize */
QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp);
uOrig = uPrev = liPerfTemp.QuadPart;
for(i = 0; i < (uFreq*30); i++){
/* update uWait and uRem based on uRem */
uWait = ((UI64)(liPerfFreq.QuadPart) + uRem) / uFreq;
uRem = ((UI64)(liPerfFreq.QuadPart) + uRem) % uFreq;
/* wait for uWait ticks */
while(1){
QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp);
uDelta = (UI64)(liPerfTemp.QuadPart - uPrev);
if(uDelta >= uWait)
break;
if((uWait - uDelta) > u2ms)
Sleep(1);
}
if(uDelta >= (uWait*2))
dwLateStep += 1;
uPrev += uWait;
/* fixed frequency code goes here */
/* along with some type of break when done */
}
timeEndPeriod(1); /* restore period */

How to force interrupt to restart main loop instead of resuming? (timing issue!)

For the last two days i wrote a program that in basic terms generates a fairly accurate user adjustable pulse signal (both frequency and duty cycle adjustable). It basically uses the micros() function to keep track of time in order to pull low or high the 4 digital output channels.
These 4 channels need to have a phase difference of 90 degrees (think a 4cyl engine) always. In order for the user to change settings an ISR is implemented which returns a flag to the main loop to re-initialise the program. This flag is defined as a boolean 'set4'. When it is false a 'while' statement in the main loop will run the outputs. When it is true an 'if' statement will perform the necessary recalculations and reset the flag so that the 'while' statement will resume.
The program works perfectly with the initial values. Phase is perfect. However when the ISR is called and comes back to the main loop, from how i understand it resumes the program in the 'while' statement from where was originally interrupted, until it finishes and re-checks the flag 'set4' to see it is now true and it should stop.
Then, even though the 'if' statement afterwards resets and re-calculates all the necessary variables the phase between these 4 output channels is lost. Tested manually i see depending on which time the ISR is called it will give different results, usually having all 4 output channels synchronised together!
This happens even though i might don't change any values (thus the 'if' routine resets the variables to exactly the same ones when you first power up the arduino!). However, if i comment out this routine and just leave the line which resets the flag 'set4' the program will continue normally like nothing never happened!
I'm pretty sure that this is somehow caused because of the micros() timer because the loop will be resumed from where the ISR was called. I've tried to do it differently by checking and disabling for interrupts using cli() and sei() but i couldn't get it to work because it will just freeze when the arguments for cli() are true. The only solution that i can think of (i've tried everything, spend the whole day searching and trying out stuff) is to force the ISR to resume from the start of the loop so that the program may initialize properly. Another solution that comes to mind is to maybe reset the micros() timer somehow..but this would mess up the ISR i believe.
To help you visualise what is going on here's a snip of my code (please don't mind the 'Millis" name in the micros variables and any missing curly brackets since it is not pure copy-paste :p):
void loop()
{
while(!set4)
{
currentMillis = micros();
currentMillis2 = micros();
currentMillis3 = micros();
currentMillis4 = micros();
if(currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
{
interval = ONTIME;
ledState = HIGH;
}
else
{
interval = OFFTIME;
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
.
.
//similar code for the other 3 output channels
.
.
}
if (set4){
//recalculation routine - exactly the same as when declaring the variables initially
currentMillis = 0;
currentMillis2 = 0;
currentMillis3 = 0;
currentMillis4 = 0;
//Output states of the output channels, forced low seperately when the ISR is called (without messing with the 'ledState' variables)
ledState = LOW;
ledState2 = LOW;
ledState3 = LOW;
ledState4 = LOW;
previousMillis = 0;
previousMillis2 = 0;
previousMillis3 = 0;
previousMillis4 = 0;
//ONTIME is the HIGH time interval of the pulse wave (i.e. dwell time), OFFTIME is the LOW time interval
//Note the calculated phase/timing offset at each channel
interval = ONTIME+OFFTIME;
interval2 = interval+interval/4;
interval3 = interval+interval/2;
interval4 = interval+interval*3/4;
set4=false;
}
}
Any idea what is going wrong?
Kind regards,
Ken
The problem is here:
previousMillis = 0;
previousMillis2 = 0;
previousMillis3 = 0;
previousMillis4 = 0;
All if statement will be true on the next loop.
Try with:
previousMillis = micros();
previousMillis2 = micros();
previousMillis3 = micros();
previousMillis4 = micros();

How can I create a kind of thread on arduino board?

I would like to receive information from a GPS receiver every second, but from sensors - every half second...
I took the code of tinyGPS and added it sensors code:
#include <TinyGPS.h>
const int RightPin = A0;
const int FrontPin = A1;
const int LeftPin = A2;
int RightVal = 0;
int FrontVal = 0;
int LeftVal = 0;
TinyGPS gps;
void setup() {
Serial.begin(115200); //GPS DATA
Serial1.begin(9600); //GPS
Serial2.begin(9600); //BLUETOOTH
}
void loop() {
RightVal = analogRead(RightPin);
FrontVal = analogRead(FrontPin);
LeftVal = analogRead(LeftPin);
Serial1.print(RightVal);
Serial1.print(", ");
Serial1.print(FrontVal);
Serial1.print(", ");
Serial1.println(LeftVal);
bool newdata = false;
unsigned long start = millis();
// Every second we print an update
while (millis() - start < 1000)
{
if (feedgps())
newdata = true;
}
gpsdump(gps);
}
Thank you very much
I'm not sure if this is what you are looking for, but you can achieve this by using interrupts. You can use a timer to generate an interrupt every 0.5 seconds and just read your sensors every time (and the GPS every two).
I haven't done this in arduino but in c with AVR microcontrollers. There must be a lot of documentation online.
from this link you can read:
attachInterrupt(function, period)
Calls a function at the specified interval in microseconds. Be careful about trying to execute too complicated of an interrupt at too high of a frequency, or the CPU may never enter the main loop and your program will 'lock up'. Note that you can optionally set the period with this function if you include a value in microseconds as the last parameter when you call it.

Using timers in ARM embedded C programming

I'm writing a pong-type game in C, which will run on an ARM board over an LCD screen. Part of the requirements for the game is something called 'magic time'.
A "magic time" period occurs at random intervals between 5 and 10 seconds - i.e, between 5 and 10 seconds after the last "magic time" period, and lasts for a random duration of 2 to 10 seconds.
I don't really understand your question (do you execute this code every second via timer interrupt, or?), but there are some errors that I see on the first sight:
while (magicTime == true) {
magicTimeLength++;
magicTime == magicTimeLength;
}
Last line (magicTime == magicTimeLength;) don't do anything - it simply evaluates if magicTime is equal to the magicTimeLength, so you will enter dead-loop.
I think that you want to do this:
Init magicTimeOccurence with random value within 5 and 10.
Init magicTimeLength with random value within 2 and 10.
Every second, if magicTimeOccurence is greater than 0, decrease
its value by one.
Once magicTimeOccurence hits 0, decrease magicTimeLength value
by one.
Check if magicTimeLength is greater than 0. If it is, it is magic
time period (so, set the magicTime flag to true). Decrement
magicTimeLength.
If magicTimeLength, set magicTime to false and go to step 1.
You should initialize your timer0 interrupt with period of 1s. I think that you accomplished it with
/* Set timer 0 period */
T0PR = 0;
T0MR0 = SYS_GetFpclk(TIMER0_PCLK_OFFSET)/(TIMER0_TICK_PER_SEC);
but make sure that is triggered every second.
Here is sample code, it should show you what I mean.
/* In void InitTimer0Interrupt() */
...
T0TCR_bit.CE = 1; /* Counting Enable */
magicTimeOccurence = 5+(rand()%5);
magicTimeLength = 2+(rand()%8);
magicTime = false;
__enable_interrupt();
}
/* In void Timer0IntrHandler (void) */
void Timer0IntrHandler (void) {
/* clear interrupt */
T0IR_bit.MR0INT = 1;
VICADDRESS = 0;
if(magicTimeOccurence > 0)
{
magicTimeOccurence--;
}
else if(magicTimeLength > 0){
magicTime = true;
magicTimeLenght--;
}
else{
magicTime = false;
magicTimeOccurence = 5+(rand()%5);
magicTimeLength = 2+(rand()%8);
}
/* take action on timer interrupt */
}

Resources