I want to make a program in which there are two dots blinking (with a break of 10ms) simultaneously, but one with delay 200ms and other with delay of 300ms. How can I play these two dots simultaneously from beginning? Is there a better way to that from following:
for(int i=1;i<100;i++)
{
if (i%2==0)
circle(10,10,2);
if (i%3==0)
circle(20,10,2);
delay(10);
cleardevice();
delay(100);
}
I would do something like this instead:
int t0=0,t1=0,t=0,s0=0,s1=0,render=1;
for (;;)
{
if (some stop condition like keyboard hit ...) break;
// update time, state
if (t>=t0) { render=1; s0=!s0; if (s0) t0+=10; else t0+=200; }
if (t>=t1) { render=1; s1=!s1; if (s1) t1+=10; else t1+=300; }
// render
if (render)
{
render=0;
cleardevice();
if (s0) circle(10,10,2);
if (s1) circle(20,10,2);
}
// update main time
delay(10); // Sleep(10) would be better but I am not sure it is present in TC++
t+=10;
if (t>10000) // make sure overflow is not an issue
{
t -=10000;
t0-=10000;
t1-=10000;
}
}
Beware the code is untested as I wrote it directly in here (so there might be syntax errors or typos).
The basic idea is having one global time t with small enough granularity (10ms). And for each object have time of event (t0,t1) state of object (s0,s1) and periods (10/200 , 10/300).
If main time reach the event time swap the state on/off and update event time to next state swap time.
This way you can have any number of objects just make sure your main time step is small enough.
The render flag just ensures that the scene is rendered on change only.
To improve timing you can use RDTSC instead of t+=10 and actually measure how much time has passed with CPU frequency accuracy.
To display the two circles simultaneously in the first round, you have to satisfy both conditions i%2==0 and i%3==0 at once. You can achieve it by simply changing
for(int i=1;i<100;i++)
to
for(int i=0;i<100;i++)
// ↑ zero here
Related
imagine I have something like this
void color(int a)
{
if (a > 10)
{
return;
}
square[a].red();
sleep(1second);
color(a+1);
}
while (programIsRunning())
{
color(1);
updateProgram();
}
but with something that actually requires a recursive function.
how can I call this recursive function to color the squares one by one.
because on its own its too fast and if the program is being updated every frame.
they instantly get colored when I want them to get colored one by one (with a delay).
sleep() will cause the current thread to stop. That makes it a bad candidate for human-perceptible delays from the main thread.
You "could" have a thread that only handles that process, but threads are expensive, and creating/managing one just to color squares in a sequence is completely overkill.
Instead, you could do something along the lines of: Every time the program updates, check if it's he appropriate time to color the next square.
const std::chrono::duration<double> color_delay{0.1};
auto last_color_time = std::chrono::steady_clock::now();
bool coloring_squares = true;
while (programIsRunning()) {
if (coloring_squares) {
auto now = std::chrono::steady_clock::now();
// This will "catch up" as needed.
while (now - last_color_time >= color_delay) {
last_color_time += color_delay;
coloring_squares = color_next_square();
}
}
updateProgram();
}
How color_next_square() works is up to you. You could possibly "pre-bake" a list of squares to color using your recursive function, and iterate through it.
Also, obviously, this example just uses the code you posted. You'll want to organise all this as part of updateProgram(), possibly in some sort of class SquareAnim {}; stateful wrapper.
N.B. If your program has little jitter, i.e. it has consistent time between updates, and the delay is low, using the following instead can lead to a slightly smoother animation:
if (now - last_color_time >= color_delay) {
last_color_time = now;
// ...
So I am trying to create a program that runs various light sequences using an Arduino board. I am not very familiar with C++ so I feel that my lack of syntax knowledge is preventing me from accomplishing my goal.
My idea is to have various light sequences that are played depending on what button is pressed on an infrared remote. The amount of time that a light is on or off may or may not be the same as that of another light. Unfortunately, the sequences do not seem to be working which indicates that the issue is likely with the toggleLight function.
I also wanted there to be a button that allows the user to pause the sequence (no matter where along the sequence it is). And once the button is pressed again, then the sequence continues where it left off. I read something about an interrupter and sleep mode using C++ but I am unfamiliar with this so it is not included in my code.
The rest of my goals I have included within my code. I created an object "light" because I was trying to create the sequence without using the delay function as the interrupt does not work well with the delay function (as far as I am aware). Then I am able to call the function toggleLight on the specific light object. However, as I previously stated the sequences are not working.
I am more familiar with OOP languages so perhaps creating an object is not the best for Arduino. If anyone has any ideas for how I can accomplish my goal it would be much appreciated.
unsigned long previousMillis = 0;
unsigned long currentMillis = millis();
//sets up the Infrared receiver for the remote controller
const int RECV_PIN = 1;
IRrecv irrecv(RECV_PIN);
decode_results results;
//Sets up the LED's pin number and light status
class light{
private:
int _pinNumber;
byte _Lstatus;
public:
//function that creates the objects with the parameters
light(int pinNum, byte Lstat){
_pinNumber = pinNum;
_Lstatus = Lstat;}
void toggleLight(long interval){
//ensures that the "interval" amount of time has passed between the last LED blink
if ((currentMillis - previousMillis) >= interval) {
// if the LED is off turn it on and vice-versa:
if (_Lstatus == LOW) {
_Lstatus = HIGH;
} else if (_Lstatus == HIGH) {
_Lstatus = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(_pinNumber, _Lstatus);
// save the last time you blinked the LED
previousMillis = currentMillis;
}
}
};
//creating four light objects with the pins and initial status of off.
light J1(13, LOW);
light J2(11, LOW);
light P1(12, LOW);
light P2(10, LOW);
void setup()
{
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
}
//Sequence 1 is a mock sequence. It will probably be longer and the intervals would not all be 1000
void seq1(){
currentMillis = millis();
J1.toggleLight(1000);
P1.toggleLight(1000);
J1.toggleLight(1000);
P1.toggleLight(1000);
J2.toggleLight(1000);
P2.toggleLight(1000);
}
void seq2(){
currentMillis = millis(); //I found that placing currentMillis = millis() here allows the lights to at least turn on
J1.toggleLight(2000);
J1.toggleLight(10);
P1.toggleLight(1000);
P1.toggleLight(0);
J2.toggleLight(1500);
J2.toggleLight(1);
P2.toggleLight(2000);
P2.toggleLight(1);
}
void loop()
{
/* So once i get the sequences working, my idea is to have different sequences play
depending on what button on the remote is pressed. However, first I want to get the sequences and
interrupter
For now I have just tried running sequence #2 but it does not work.. Neither does Sequence #1. */
seq2();
//I MADE THESE LINES OF CODE COMMENTS FOR NOW. UNTIL I GET THE REST OF THE PROGRAM WORKING
/*if (irrecv.decode(&results))
{
switch (results.value) {
case : 0xf00000 // When button #1 sequence one plays
seq1();
break;
case : 0xf00000 // when button #2 is pressed, sequence two plays
seq2();
break;
*/
}
I can see that you haven't yet got around to understanding the flow of code inside the Arduino. Here's a quick tutorial to get you up and running.
Basically, your code is not being processed sequentially. So when the processor is moving through seq() and gets to the first if statement in 'J1.toggleLight(2000);' and finds that the condition is not met (i.e. the 2000 milliseconds have not yet passed,) it immediately moves on to the second line in seq(). The issue with this is that when it does meet the condition at the second line it will reset the 'previousMillis' value which all the lights depend on.
Thus you should dedicate a clock for each light by moving in 'previousMillis' into the class as a member.
class light{
private:
int _pinNumber;
byte _Lstatus;
unsigned long previousMillis = 0;
This way each light will be able to keep track of its own time without conflicting with the other lights. This will lead to your lights flickering at a frequency of 1/interval which I doubt is what you want.(it wont even do that with each light getting toggled twice in the seq() functions. Try removing the second calls and see hat happens) This brings me to the second issue.
The second issue is with the way you set up your sequences. Since you want to the lights to operate sequentially you'll need to find the accumulated time which crosses out the chance of using a class, unless you're willing to implement a scheduling mechanism that takes account the interval and arrangement of each instance. Seems a bit impractical imo.
I think you should ditch the class and use a simple function that that accepts the eight values that each sequence requires. Then you could utilize if statements to manipulate the states of the lights.
I hope the answer made some sense.
Good luck.
In my project, function clipsUpdate reads some facts which are set by CLIPS without the interference of my C++ code. Based on the read facts, clipsUpdate calls the needed function.
void updateClips(void)
{
// read clipsAction
switch(clipsAction)
{
case ActMove:
goToPosition (0, 0, clipsActionArg);
break;
}
}
In goToPosition function, a message is sent to the vehicle to move to the specified position and then a while loop is used to wait until the vehicle reaches the position.
void goToPosition(float north, float east, float down)
{
// Prepare and send the message
do
{
// Read new location information.
}while(/*Specified position reached?*/)
}
The problem is that updateClips should be called every 500 ms and when the goToPosition function is called, the execution is blocked until the target location is reached. During this waiting period, something may happen that requires the vehicle to stop. Therefore, updateClips should be called every 500 ms no matter what, and it should be able to stop executing goToPosition if it's running.
I tried using threads as following, but it didn't work successfully with me and it was difficult for me to debug. I think it can be done with a simpler and cleaner way.
case ActMove:
std::thread t1(goToPosition, 0, 0, clipsActionArg);
t1.detach();
break;
My question is, how can I check if the target location is reached without blocking the execution, i.e., without using while?
You probably want an event-driven model.
In an event-driven model, your main engine is a tight loop that reads events, updates state, then waits for more events.
Some events are time based, others are input based.
The only code that is permitted to block your main thread is the main loop, where it blocks until a timer hits or a new event arrives.
It might very roughly look like this:
using namespace std::literals::chrono_literals;
void main_loop( engine_state* state ) {
bool bContinue = true;
while(bContinue) {
update_ui(state);
while(bContinue && process_message(state, 10ms)) {
bContinue = update_state(state);
}
bContinue = update_state(state);
}
}
update_ui provides feedback to the user, if required.
process_message(state, duration) looks for a message to process, or for 10ms to occur. If it sees a message (like goToPosition), it modifies state to reflect that message (for example, it might store the desired destionation). It does not block, nor does it take lots of time.
If no message is recived in duration time, it returns anyhow without modifying state (I'm assuming you want things to happen even if no new input/messages occur).
update_state takes the state and evolves it. state might have a last updated time stamp; update_state would then make the "physics" reflect the time since last one. Or do any other updates.
The point is that process_message doesn't do work on the state (it encodes desires), while update_state advances "reality".
It returns false if the main loop should exit.
update_state is called once for every process_message call.
updateClips being called every 500ms can be encoded as a repeated automatic event in the queue of messages process_message reads.
void process_message( engine_state* state, std::chrono::milliseconds ms ) {
auto start = std::chrono::high_resolution_clock::now();
while (start + ms > std::chrono::high_resolution_clock::now()) {
// engine_state::delayed is a priority_queue of timestamp/action
// ordered by timestamp:
while (!state->delayed.empty()) {
auto stamp = state->delayed.front().stamp;
if (stamp >= std::chrono::high_resolution_clock::now()) {
auto f = state->queue.front().action;
state->queue.pop();
f(stamp, state);
} else {
break;
}
}
//engine_state.queue is std::queue<std::function<void(engine_state*)>>
if (!state->queue.empty()) {
auto f = state->queue.front();
state->queue.pop();
f(state);
}
}
}
The repeated polling is implemented as a delayed action that, as its first operation, inserts a new delayed action due 500ms after this one. We pass in the time the action was due to run.
"Normal" events can be instead pushed into the normal action queue, which is a sequence of std::function<void(engine_state*)> and executed in order.
If there is nothing to do, the above function busy-waits for ms time and then returns. In some cases, we might want to go to sleep instead.
This is just a sketch of an event loop. There are many, many on the internet.
I have a while loop which displays things on window using openGL, but the animation is too fast compared to how it runs on other computers, so I need something in the loop which will allow to display only 1/40 seconds after previous display, how do I do that? (I'm c++ noob)
You need to check the time at the beginning of you loop, check the time again at the end of the loop after you've finished all of your rendering and update logic and then Sleep() for the difference between the elapsed time and the target frame time (25ms for 40 fps).
This is some code I used in C++ with the SDL library. Basically you need to have a function to start a timer at the start of your loop (StartFpsTimer()) and a function to wait enough time till the next frame is due based on the constant frame rate that you want to have (WaitTillNextFrame()).
The m_oTimer object is a simple timer object that you can start, stop, pause.
GAME_ENGINE_FPS is the frame rate that you would like to have.
// Sets the timer for the main loop
void StartFpsTimer()
{
m_oTimer.Start();
}
// Waits till the next frame is due (to call the loop at regular intervals)
void WaitTillNextFrame()
{
if(this->m_oTimer.GetTicks() < 1000.0 / GAME_ENGINE_FPS) {
delay((1000.0 / GAME_ENGINE_FPS) - m_oTimer.GetTicks());
}
}
while (this->IsRunning())
{
// Starts the fps timer
this->StartFpsTimer();
// Input
this->HandleEvents();
// Logic
this->Update();
// Rendering
this->Draw();
// Wait till the next frame
this->WaitTillNextFrame();
}
I have a robot with encoder feedback, and i want to use functions that move a robot a certain distance and turn it a certain angle, so for example:
void loop(){
if (Obstacle==false){ // if no obstacles
forward(1000); // move forward 1000 mm
backward(1000); // move backward 1000 mm
//...
}
}
Forward Function:
void forward(int distance){ // distance in mm
int desiredRotationNumber= round(distance/circumference) ;
int desiredTicks = encoderResolution * desiredRotationNumber;
if (counter < desiredTicks) // variable counter counts the pulses from the encoder
{
analogWrite(motor,255);
}
else
{
analogWrite (motor,0);
}
}
The problem is that if i use the condition "if" my forward function will execute only once and then the program jumps to the next function, but if i use the "while loop" my move functions will execute correctly but i won't be able to manage sensors or anything.
What you probably want is to cut your moves in increments, and check the sensors in between each of these increments:
while (distance > 0 && !Obstacle){
forward(step);
distance-=step;
check_sensors();
}
With multithreading, you could make those operations (moving and sensing) work asynchronously, and use some kind of event posting to warn each thread of a change. Here we're simulating that functionality by interwinding the tasks (you could also look into coroutines for a similar, yet much more effective idea).