Show Posts
Pages: 1 2 [3] 4 5 ... 34
31  Forum 2005-2010 (read only) / Troubleshooting / Re: arduino reads only values from 0 to 500 on: August 05, 2008, 12:49:30 pm
You can also use the internal pull-up to cause it to read 5 V when nothing is connected (a good test would be to enable this pull-up and perform an analog read to see if you get 1023).  The internal pull-up is only around 20k or 30k, I believe, so it might influence your analog readings more than a 100k pull-up to ground or Vcc.

- Ben
32  Forum 2005-2010 (read only) / Troubleshooting / Re: Burning sketches to the Arduino board with an on: June 30, 2008, 01:48:10 am
You don't need to post the same thread in multiple places.  I have responded in your other thread.
33  Forum 2005-2010 (read only) / Troubleshooting / Re: odd variable problem. on: June 16, 2008, 12:46:02 am
You are claiming that tube isn't getting executed when you pass it a variable but it is when you pass it a literal.  Obviously this makes no sense, so why not put a debug statement in there to figure out exactly what is going on?  My guess is that your global "number" has a bad value.

- Ben
34  Forum 2005-2010 (read only) / Troubleshooting / Re: odd variable problem. on: June 16, 2008, 12:26:42 am
Have you tried putting debug print statements inside tube()?  Does your program use a lot of RAM (i.e. do you have any large arrays)?

- Ben
35  Forum 2005-2010 (read only) / Troubleshooting / Re: odd variable problem. on: June 15, 2008, 11:47:26 pm
Can you be more explicit than just saying "it doesn't work"?  What is "number"?

- Ben
36  Forum 2005-2010 (read only) / Troubleshooting / Re: Missing pulse detector misses pulse! on: June 15, 2008, 01:42:51 am
Ah, thanks.  I was seeing the pulseIn() prototype in wiring.h and it definitely wasn't giving a default value for timeout!

- Ben
37  Forum 2005-2010 (read only) / Troubleshooting / Re: Missing pulse detector misses pulse! on: June 14, 2008, 09:14:54 pm
I take back my previous statement, then.  Where is the two-argument version of pulseIn() defined?  I can't find it in the wiring files...

- Ben
38  Forum 2005-2010 (read only) / Troubleshooting / Re: Missing pulse detector misses pulse! on: June 13, 2008, 11:05:29 pm
Quote
What happens if you don't specify the timeout value?
You get a compiler error?  I haven't tried pulseIn(), but looking at the code in wiring.h and wiring_pulse.c, it looks like you don't have the option of calling it pulseIn() with only two arguments...

- Ben
39  Forum 2005-2010 (read only) / Troubleshooting / Re: Missing pulse detector misses pulse! on: June 09, 2008, 12:40:39 pm
Quote
 if (newtime > (savedtime +( savedtime / 2))
Maybe also replace this with

if (newtime > (savedtime + (savedtime >> 1)))

I'm not sure if the compiler is smart enough to detect division by a power of two, but I never like to take the chance.  If for some reason it's not, division takes a whole lot longer than bit-shifting, which takes a single instruction cycle to perform on a byte.

Also, if possible, work with unsigned integers (or even unsigned chars) rather than longs (they're half the size and hence the mathematical operations involving them are much faster).  For example, you are expecting your pulses to be only a few hundred microseconds, so you should be able to safely cast the result of the pulseIn() call to an unsigned int.

- Ben
40  Forum 2005-2010 (read only) / Troubleshooting / Re: Unwanted interrupt to TDC marker on: June 03, 2008, 04:19:16 am
Hmm, at the moment I can't see any reason why you would miss a pulse.  What is the width of each input pulse?  Maybe as a first step you can confirm that you are indeed missing pulses.  It could be helpful to figure out at what rate you are missing them and whether the rate is affected by your RPM.  My suggestion would be to use a hardware timer1 running at the I/O clock / 8 (2 MHz) to measure the time between each successive pulse while your input source is running at a relatively constant RPM.  Your blink interrupt can check the timer1 count and then reset it for every received pulse.  If the pulse length is ever more than, say, 1.8 times what you expect (or maybe if it's ever significantly greater than a running average you are maintaining), increment a "missed pulse counter" variable.  After a certain number of seconds have elapsed, output the value of this counter to get a measure of dropped pulses per second, or, maybe better yet, of total pulses per dropped pulse.  You can then conduct this test at a variety of different RPMs to see whether there's any correlation.

- Ben
41  Forum 2005-2010 (read only) / Troubleshooting / Re: Unwanted interrupt to TDC marker on: June 02, 2008, 04:56:41 pm
What percentage of the pulses are you missing?  What is the duration of the input pulses and at what frequency are they coming?  Are you using an oscilloscope to verify that you are missing pulses?

- Ben
42  Forum 2005-2010 (read only) / Troubleshooting / Re: Who can spot what's wrong with this code? on: June 02, 2008, 12:48:27 pm
As mem has said, digitalRead(7) is equivalent to:

PIND & (1 << PD7) ? 1 : 0;

Otherwise, PIND & (1 << PD7) equals 0 if the pin is low and equals (1 << PD7) = 128 if the pin is high.


One additional warning I want to point out:

The bitshift operators << and >> have very low orders of precedence.  I think they're still higher than bitwise and (&) and bitwise or (|), so your code should still work correctly, but they are lower than things like + and -, and this can lead to trouble.  For example:

1 + 1 << PD7 = 2 << PD7

For that reason, I recommend you put parentheses around bitshift expressions if there's any doubt at all about order of precedence.


- Ben
43  Forum 2005-2010 (read only) / Troubleshooting / Re: Problems using timers inside interrupts on: June 01, 2008, 05:55:57 pm
Very cool.  Good luck with your project!

- Ben
44  Forum 2005-2010 (read only) / Troubleshooting / Re: Problems using timers inside interrupts on: June 01, 2008, 05:20:08 pm
When you enter an ISR, the global interrupt enable flag bit in SREG gets cleared, and when you exit the ISR, it gets restored.  This means that no other ISRs will be executed while you are in the current ISR.  The way around this is to re-enable interrupts in your ISR using the sei() command (or you can declare your ISR with a special attribute that will cause it to automatically re-enable interrupts at the very start, even before it pushes data onto the stack, but I don't remember the exact syntax for accomplishing this).

Note that if you re-enable interrupts in your ISR, you could potentially run the risk of your ISR interrupting itself.  If this happens repeatedly, you pretty much have an infinite-recursion situation that will quickly overflow your stack.  The solution is to explicitly disable the current ISR trigger before re-enabling the global interrupt flag.  For example:

ISR(TIMER1_OVF_vect)
{
  TIMSK1 &= ~(1 << TIOE1);  // disable timer1 overflow interrupt
  sei();  // re-enable global interrupts so that other ISRs can execute

  do some stuff;

  TCNT1 = 0;
  TIFR1 |= 0xFF;  // clear any pending timer1 overflow interrupts
  TIMSK1 |= 1 << TIOE1;  // re-enable timer1 overflow interrupts
  // the previous lines make sure that we can now get out of this ISR
  // without this ISR interrupting itself
}


If you just want to time things in an interrupt, you can rely on the timer count registers TCNTx.  Timers will continue to run while you are in the ISR; it's only their associated interrupts that will be disabled by default.  So if you want to wait for a specific length of time and you know that timer0 is running at a specific clock speed, you could do something like:

ISR(blah)
{
  unsigned char time = TCNT0;
  while (TCNT0 - time < 100)  // delay for a certain amount of time
    ;
  other code here
}

Or another option is to use a loop delay.  The file <util/delay.h> gives you the function _delay_ms() and _delay_us() that use the clock speed defined by F_CPU to achieve delays that will be correct independent of your clock speed.  Unfortunately these delays are restricted to short durations when the clock speed is high.  If F_CPU is 20 MHz, for example, the maximum you can delay with _delay_ms() is something like 13 ms.  The solution is to make your own function that uses these functions:

void delay_ms(unsigned int time_ms)
{
  while (time_ms--)
    _delay_ms(1);
}

This delay will work inside an ISR because it doesn't rely on interrupts for its timing.

Lastly, in general your guiding ISR approach should be: "get in and get out."  It's usually not a very good practice to spend a lot of time in an ISR, because this interrupt will happen in the middle of your code and could introduce a long delay into a routine that was not expecting it.  For example, maybe you're trying to measure the length of a short pulse when this ISR occurs.  If you spend a few milliseconds in your ISR and the pulse is only a few microseconds long, you might miss the pulse entirely, or you might measure its length as a few milliseconds rather than microseconds.  If you need your ISR to accomplish complicated/long things, you should, if possible, just have the ISR set up events that can then be carried out in your main loop.

For example:

volatile unsigned char event = 0;

ISR(something)
{
  if (blah)
    event = 1;
}

loop()
{
  if (event == 1)
  {
    do the long/complicated thing
    event = 0;
  }
}

In my experience, interrupts are one of the hardest things to use well in embedded programming.  Because of their often non-deterministic nature and the fact that they can occur in the middle of an operation that you might think is uninterruptable, they can lead to bugs that are incredibly difficult to track down.


- Ben
45  Forum 2005-2010 (read only) / Troubleshooting / Re: Problems using timers inside interrupts on: June 01, 2008, 02:55:07 pm
I made a post that partially addresses this issue here.  I have to go but I'll add more later.

- Ben
Pages: 1 2 [3] 4 5 ... 34