Let's Make Robots!

Trying to replace my Delays with Intervals, so i can do other things!

Hi there Everyone.

My last 2wd rover project (cyclops), ran the motors for periods of time based on delays, as in:

Turn motors on

Delay

Turn motors off

I want to add edge detection to the project, so i can run it on a desk. stage one is to replace the delays with "wait without delay" functions, to allow me to monitor the front sensors while it moves.

As far as i can see i have done what i think i should do but it doesnt work.

This should be the code, on paste bin:

http://pastebin.com/qvZrQjUj

It is seperated into tabs in my sketch, I have pasted the other tabs (which contain various voids) into the sketch, just above the loop.

This is how i THINK it is working (except it isnt working)

 

Create three interval timers, lines 42, 43, 44. Current time, previous time, and the interval in millis.

at the end of setup, start the "current" clock. Line 109.

the system carries out direction scans (voids vert and hori) as defined in the loops phase.

once it has carried these out, it defines "previous as current" line 296

it then carried out movements based on the directions determined in the sweeps. the movements are under the void "decisions" which start at line 159. there are three options, one each for straight on, right and left. The associated references to the time intervals are in each of these sections.

The bot still turns in the correct directions, but continues to spin, until the servo scan is completed again. I want it to write a "release" at the end of the intervals.

once i have it working with a basic interval of 1000, i will write the intervals as variables, depending on the angles detected.

(However that is the next phase. i had it working like that perfectly when i was using delays, hence the reference to Vert and Hori Delays which currently dont do anything)

Any advice would be great. Cheers All!

PS, my bizzare post formatting is supposed to make it easier to see the details in the post, hope it helps!

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

...but it's wrong. Very wrong...

You said "Create three interval timers, lines 42, 43, 44. Current time, previous time, and the interval in millis.". That code does not "create" any timers. You are just declaring 3 variables and assigning their initial value.

Then 'at the end of setup, start the "current" clock. Line 109.' That line "unsigned long current = millis();" does not start anything. What you are actually doing there is creating a new variable with the same name and type as the one on line 43, but visible only within the wile loop within the setup function, and then you store the number of milliseconds since the system started in that variable. This means that the variable will be recreated and assigned the value of millis() until millis is larger than 5000 when the while finshes and the variable goes out of scope and anything stored in it is lost.

 

"the system carries out direction scans (voids vert and hori) as defined in the loops phase." Right, it does carry direction scans, but they are wrong for two reasons:

  1. They take a long time (about 2.2 seconds) and can't be interrupted. So whatever you set your motors to do in Decisions() will happen for AT least 2.2 seconds, even if your interval is 1 second
  2. The way you wrote your code, the array with the readings is just using up RAM and complicating the code.

 

"it then carried out movements based on the directions determined in the sweeps. the movements are under the void "decisions" which start at line 159. there are three options, one each for straight on, right and left. The associated references to the time intervals are in each of these sections.

The bot still turns in the correct directions, but continues to spin, until the servo scan is completed again. I want it to write a "release" at the end of the intervals."

The code in the loop() function is wrong, you keep assigning the value in current to previous, but you never update current so both current and previous will be 0 until the end of time.

Because current and previous are both 0 all the time, the Decisions function does not work as you would expect, it always starts the motors in some direction but it never turns them off because current-previous is always smaller than interval (0-0)<1000.

 

To fix this mess, you need to update the current millis on each loop, like this:

//********************************

  previous = current;

  current = millis();

//********************************

Then you need to break up the sweep functions into steps that can be used without using delays.

I could show you how to write that code but you will learn more by trying to do it yourself.

If the electrical output of your sensors (the ones that look for the edge of the table) can be designed to effectively change logic levels (either low to high or high to low) when the edge of the table is present, you could trigger an interrupt on rising or falling edge.  You could use INT1 and INT0 interrupts if you don't need more than two interrupts for your sensors, otherwise you can configure pin change interrupts (PCINT) which are available for nearly every pin but less configurable.  I'm not sure if the Arduino library takes advantage of PCINT so you may need to read the datasheet or find a third party library to use them.

It isn't very clear to me what all of the sensors you are using so what I mentioned above may or may not be applicable.

Like Bajdi, I won't attempt to read other peoples code but this is a problem I learned to overcome a long time ago. There are two possible solutions to your problem.

The simplest method is what Chris (and I think Bajdi) suggested and it has the advantage that you can have multiple timers for different functions and not conflict with timer interrupts used by other commands or libraries. The only disadvantage is that it is less precise as it depends on how quickly your main loop repeats.

If timing is critical then use a timer interrupt. This is the most difficult solution for a beginner but worth the effort to learn. RobotFreak wrote a good tip/walkthrough here: http://letsmakerobots.com/node/28278.

Note that if your interrupt service routine is too big then it may interfer with other functions so keep it as concise as possible. When I wrote my microM library I had to use a digital oscilloscope to debug my code so it did not make my servos jitter. I suggest buying / using an Arduino Mega or compatible board as they have more timers and more pins. This can equate to fewer headaches.

 

The millis 5000 section is for a different action, it seems to work ok, but i will remove it incase it is messing some stuff up.

I have been following that example as far as i can see

I will have a looksee thanks bajdi

Yes in the Arduino IDE you will find the example sketch "blink without delay". For me it is the mother of all sketches. If you want  to write some decent code you must learn to use timers. Take a very good look at that sketch :)

The first thing I saw was "if (millis<5000)"  --this is only going to happen once (until the millis() counter rolls over which is in days, I think).

 

In general, I think you want to do this:

long remTime;

setup()
{
   remTime=millis()
}

 

loop()

if (millis()>remTime+your_delay)
{
   do something
   remTime=millis();

 

 

There is an example for this. I think it is called "blink without delay"

Looking at other peoples code makes my head hurt, but...

I don't use the delay function in void loop. Here are some sketches that I have written that might be helpful:

http://www.bajdi.com/something-different-a-crash-robot/

http://www.bajdi.com/obstacle-avoiding-robot-made-from-cheap-parts/

And I'm very proud of this, my no delay servo code:

http://www.bajdi.com/sweeping-servos-with-arduino/