Show Posts
Pages: 1 2 [3] 4 5 ... 14
31  Forum 2005-2010 (read only) / Syntax & Programs / Re: microseconds on: May 27, 2007, 11:19:23 am
There is not a call for measuring microseconds.
You could use delayMicroseconds() and polling to repeatedly wait a while and check to get a rough idea of how long it was.
You could also look at TCNT1 which is a 16 bit register that increments every 4 microseconds in the standard Arduino configuration. It is going to roll over frequently, and you really should block interrupts around reads to it, like this...
myVar = TCNT1;
... which assumes you know interrupts were off when you started. (true for normal Arduino code).
32  Forum 2005-2010 (read only) / Syntax & Programs / Re: Software reset on: May 26, 2007, 10:57:34 am
The reset pin is brought out on the ICSP header, pin 5. If you tie any another output to that pin, then when you enable that output and pull it low you will reset the processor. Part of the reset process will release the pin and allow it to come high again.

If you use Digital 12, (port B pin 4) it doesn't have a high value function (unless you are using SPI), is also on the header at pin 1 and with a little jumper wire you can connect them. Do not use Digital 13, you can connect that with just a jumper, but it gets strobed by the bootloader to flash your LED, you will perpetually reset.

33  Forum 2005-2010 (read only) / Syntax & Programs / Re: can the arduino generate frequencies accuratel on: May 22, 2007, 11:44:03 pm
The hardware timers can do that. You need to pick the mode where the input capture register is the top and use the output capture register to clear the pin (it will set at bottom). Then just set the output capture register to something like 1 and you will get a short strobe with a period governed by the input capture register and the prescaler.
34  Forum 2005-2010 (read only) / Syntax & Programs / Re: can the arduino generate frequencies accuratel on: May 21, 2007, 11:49:29 pm
Ok, I library-ized the timer2 frequency generator code. will tell you all about it and has the code. This library lets you make absolutely stable square wave signals from 1MHz down to about 30Hz on a 16MHz Arduino.

I might mention that until 0008 comes out you might have to add a
#define clockCyclesPerMicrosecond() (16)
to the libraries I have been uploading recently.
35  Forum 2005-2010 (read only) / Syntax & Programs / Re: can the arduino generate frequencies accuratel on: May 20, 2007, 11:18:40 am
delayMicroseconds will not overflow, though you can't pass an argument larger than 10000 or so. If you disable interrupts then delayMicroseconds will take the same time delay for each call, but millis() will stop and your serial input will not work.

If you leave the interrupts enabled then then every 1024 microseconds the timer0 interrupt will fire and delay you an extra few microseconds. Arriving serial characters will also delay you a similar amount.

I should probably write a library or something for this, but I generally reprogram one of the hardware timers to make a stable output frequency.
36  Forum 2005-2010 (read only) / Syntax & Programs / Re: read multiple pins at once? on: May 22, 2007, 05:02:04 pm
http:// I'll go fix the tutorial.
37  Forum 2005-2010 (read only) / Syntax & Programs / Re: read multiple pins at once? on: May 22, 2007, 01:49:26 pm
wandrson is correct about the speed of the digitalRead and digitalWrite functions.
In 0008 they will be much faster, though still around.. 4uS I think.

Also in 0008 is an API to get the IO registers and bitmask for a given pin number so you can easily do the fast access if you need to without worrying about ports and bit shifting.

It is all a tradeoff. I could have written the digitalRead and write functions to take about 1uS, but then the code size would go up. I figured if you needed better than 4uS you were probably going to be counting instruction cycles anyway and you could take care of yourself.
38  Forum 2005-2010 (read only) / Syntax & Programs / Re: read multiple pins at once? on: May 22, 2007, 01:01:23 am
A quick look at the pin mapping diagram shows pins 0-7 are all on port d. You can access the bits as a byte using PIND. I would use the bitwise AND operator (&) to mask off the two pins you don't care about and then check the result...
if ( (PIND & 0xfc) != 0xfc) {
    // then one of them is low
0xfc is a hexadecimal B11111100. I have parenthesis around the '&' operation because the bitwise operators have surprisingly low operator precedence and you can easily trick yourself with them, and they are required in this case but I always put them in for bitwise operators.

I didn't compile it to check, but that expression in the 'if' probably takes around 10 cycles to execute (it is a bit long because bitwise operations have to be done at 'int' size by the C spec). This compares to a digitalRead() that takes something like 100 cycles in arduino-0007.
39  Forum 2005-2010 (read only) / Syntax & Programs / Re: Help needed for code optimization on: May 06, 2007, 10:51:30 am
That "delay(50)" is your slowdown. Your code would be ok for 1 servo, but with three, and delaying 50ms on each one you are going to be looking at 6 updates per second.

I might be tempted to just store the desired value when the serial data comes in, then at the top of my loop check millis() and if it is at least 40ms since my last pusling, then pulse all three servos and not the time I did it.

That way your pulse interval would be indepentent (mostly) of the number of servos and as a side effect you wouldn't have to keep sending the same value from the host to keep the servos in place, they would stay in the last position if the host got busy with something else and delayed an update.

(Actually, I'd use a cool servo library, but I'm not done polishing so I haven't posted it.)
40  Forum 2005-2010 (read only) / Syntax & Programs / Re: reset millis() ? on: May 15, 2007, 11:08:14 am
Ah, then what needs doing is to rewrite the function as a test to see if a certain amount of time has passed...
int after(unsigned long start, unsigned long interval)
        unsigned long finish;
        unsigned long now = millis();

        if ( interval == 0) return;
        finish = start + interval;

        if ( finish < start) {    // we need to roll over
            if ( now < start && now >= finish) return 1;
        } else {                // we can't roll over
            if ( now >= finish || now < start) return 1;
        return 0;

Then you can use it in your code like this...
void blah() {
  time0 = millis();
  while ( != 3) {  
    if ( after( time0, 3000) return;

You could of course do this...
extern volatile unsigned long timer0_overflow_count;
timer0_overflow_count = 0;
... but you never know what code you would break in various libraries and internal functions that are using that counter and don't expect it to be reset, not to mention that as an undocumented API it could change at any moment.
41  Forum 2005-2010 (read only) / Syntax & Programs / Re: reset millis() ? on: May 15, 2007, 09:22:11 am
Here is an example of delaying safely in the face of overflows...
void delayMillis(unsigned long tc)
        unsigned long start = millis();
        unsigned long finish;
        unsigned long now;

        if ( tc == 0) return;
        finish = start + tc;

        if ( finish < start) {    // we need to roll over
            for(;;) {
                now = millis();
                if ( now < start && now >= finish) return;
        } else {                // we can't roll over
            for(;;) {
                now = millis();
                if ( now >= finish || now < start) return;

And you could reset the millis counter by making an extern variable declaration for it in your sketch and setting it to zero, but you might expect "bad things" to happen in any other bit of code that was using millis() for timing.
42  Forum 2005-2010 (read only) / Syntax & Programs / Re: Stop after # of loops on: May 06, 2007, 07:48:50 pm
There isn't a concept of stopping. A possible solution would be to keep a count of how many loops you had executed and then not blinking after that many have passed. Something like...
void loop()
  static int loops = 0; // this static variable holds its value between calls to loop()

  if ( loops > 10000) { // if we have looped too long, then turn off
    return; // don't do the rest of the loop function
  } else loops++;  // don't increment after we hit 10000 or we wrap eventually

  // blah blah, the rest of your loop function goes down here

Your loop() function will still be called continuously, but it won't be blinking anymore.

(Note: If battery life were an issue, there are ways to halt the processor, but that isn't an issue when you are plugged in.)
43  Forum 2005-2010 (read only) / Syntax & Programs / Re: Gyro Integration and Trig? on: April 27, 2007, 05:54:14 pm
Reading high resolution time is tricky on an Arduino. You can use millis() if you only need to be accurate to something near milliseconds. I'd go with that, you probably won't be making more than 100 updates per second anyway.

To get more accurate you need to look at the timer registers and the millis() value and try to figure it out from there, but that gets tricky. The ATmega8 manual talks at great length about the timer registers. Remember in the Arduino they are being used for the PWM outputs, so if you change their clock rates or cycle times you will mess up the PWMs.
44  Forum 2005-2010 (read only) / Syntax & Programs / Re: Gyro Integration and Trig? on: April 27, 2007, 09:27:06 am
When they say to "integrate the rate", that is just a fancy way of saying "add up all the changes". Let's say you know your starting angle is S. If after M microseconds you check your gyro and it says you are changing at a rate of R degrees/second then you update S by adding R times M/1000000. (that constant is converting the microseconds to seconds to match the units of R.) Then you keep doing this, hopefully fast enough to catch all the little bumps and valleys in your R.

As you say, S will slowly drift off and your robot will fall over. You can probably use your accelerometers to also compute an angle in certain circumstances and use that to correct S when possible.

Floating point math and trig take a large portion of the available memory. Fortunately, you don't really want to know the tangent or arctangent. You want to know what the component of a vector in the direction of another vector is. You want to learn about "dot products" which just use a little multiplication and addition and work very nicely with fixed point numbers. I point you to a quick tutorial on 3D math (but maybe follow the 2d link at the top to get started) and I haven't been through it, but looks very thorough and I plan to read it myself before I build a motor controller.

If you decide you must do trig... then make yourself a constant array of 256 bytes that are the first 1/4 cycle of a sine wave scaled from 0 to 255. With that and a little bit of flipping you can compute the sine and cosine. You can do linear interpolation for better resolution if needed and also scan through it using a binary search algorithm for your inverse sine and cosine functions. Somewhere in the forums I posted one, though none of the supporting functions, just the array of bytes.
45  Forum 2005-2010 (read only) / Syntax & Programs / Re: Start bootloader from within program? on: April 24, 2007, 02:11:26 pm
I tried to accomplish a reset using the watchdog timer. This will not work. You will end up in an infinite reset loop as the bootloader doesn't tickle the watchdog and it stays enabled when it goes off.

In software the best you can do is jump to the reset vector (the instruction at 0x0000) after initializing all the important registers (at least turn off all the outputs and set all the digitalWrite()s to 0 to kill the pull up resistors). I had the code somewhere, but I think I ripped it out since I didn't trust my ability to find and initialize all the registers.

If you have an extra pin, you could wire it to the reset pin and pull it low to make a real reset.
Pages: 1 2 [3] 4 5 ... 14