Show Posts
Pages: [1] 2 3 ... 14
1  Forum 2005-2010 (read only) / Troubleshooting / Re: Wire and OneWire conflicts? on: March 29, 2007, 12:16:42 am
I generally suspect running out of SRAM when combining things makes them fail. All those strings that you Serial.print take SRAM, so those are suspect as well. A cruel twist that the very thing you might use to debug causes the bugs.

I looked back over OneWire now that I have more experience in the Arduino environment. It is probably sensitive to interrupts. I'd wrap the read bit and write bit routines in cli() and sei() calls to disable interrupts in them, but you would also need a tweeked delayMicroseconds because the one in 0007 turns on interrupts as it exits.

Other than that I don't see any resource that would conflict. I suspect SRAM usage.
2  Forum 2005-2010 (read only) / Troubleshooting / Timing the little things on: March 28, 2007, 03:54:19 pm
I have stumbled several times now by poorly guessing how long a function takes. I suspect others have as well. For example, I see people looking for help debugging code that measures a couple of microseconds between digitalWrite() calls, neglecting that these calls take something near 10 microseconds each.

Here is a way to very accurately time how many clock cycles a tiny operation takes without an oscilloscope.

void setup()

void loop()
  unsigned long loops = 0;

  // TCNT0 is the timer used to compute milliseconds and drive PWM0.
  // It is an 8 bit value that increments every 64 clock cycles and
  // rolls over from 255 to 0.
  // We repeatedly run the test code as the timer goes from 156 through 255
  // which gives use 64*100 clock cycles.
  // In practice this works for timing operations that take from 1 to
  // hundreds of clock cycles. The results get a little chunky after that
  // since the last one will have gone a fair bit past the end period.
  while( TCNT0 != 155);        // wait for 155 to start
  while( TCNT0 == 155);        // wait until 155 ends
  cli(); // turn off interrupts
  while( TCNT0 > 150 ) {       // that 150 acknowledges we may miss 0
    // vvvvvv---- your code to be timed
    // ^^^^^^---- your code to be timed
  sei(); // turn interrupts back on
  Serial.print("loops: ");
  Serial.print(" clocks: ");
  Serial.print( (int) (( 100UL*64UL) / loops) - 8 /* empty loop cost */, DEC);


Run that and watch your serial monitor at 9600 bps and you will see how many clock cycles a digitalWrite() takes.

The interesting section is where I have a digitalWrite(). You would replace that line with something you cared to time. If it is a simple computation you will have to be careful that it doesn't get optimized away. Assigning the result to a "volatile" variable and using "volatile" variables as inputs is a good tactic, but it can still do tricky things with your constants.

(I made this because I was dismayed at how slow digitalWrite() was. I've recoded it and it is now much faster, smaller, and saves 100+ bytes of RAM. I'll write about that in another entry.)
3  Forum 2005-2010 (read only) / Troubleshooting / Re: a small little thing on: March 17, 2007, 10:10:10 am
An Arduino with a some extra bits and pieces would do nicely. Generally if you are making digits on LEDs you will use a 7 segment display. A quick peek at common large seven segment LEDs ( shows that they are made by putting a bunch of LEDs in series. This is good and bad. You won't need a lot of current, but you will need 9.25 volts for a 4 inch tall display. You only get 5v out of an arduino pin.

The easiest solution might be:
 1) Stick with a 2.3" display. This only needs 7.4v@20ma.
 2) Use the raw power pin of the arduino, this is called 9v but is probably more like 10 to power the LEDs.
 3) Use a (9-7.4)/(0.020) = 130... a 150 ohm resistor in series with each segment to keep the current under 20ma.
 4) Use the LED driver tutorial...
 5) Power the 4794 chip from the 5v power, not the raw!
 6) If you use the decimal point it will need a much larger resistor, it has half the voltage drop.

From there it is just a matter of blinking the lights.

You could also just use some cheap tiny transistors as switches instead of the 4794, but then you'd need to use all 13 of the digital outputs (stay away from digital0, you'd need to move a jumper after programming, and you don't need the upper lefthand segment of the lefthand digit for numbers 1-30) and you'd do a lot more soldering. And you know someone will want to put a 4 or a zero in that lefthand digit as soon as they see it.

If you get seduced by the giant 4" leds... you might give it a go with the transistor method and leave out the current limiting resistors. It looks like the so called 9v DC power supply probably puts out enough voltage to light them without putting out enough to fry them. But you never know about wall wart power supplies. Some of them put out quite a bit more voltage than they say. You could use a regulated 12v supply with a 150 ohm resistor too.

4  Forum 2005-2010 (read only) / Troubleshooting / Re: When programs don't work on: March 17, 2007, 01:12:34 am
I found a nice resource on the avr-gcc code generation in the avr-libc manual.
Their FAQ leads to all sorts of interesting facts about code size optimization and keeping strings out of RAM.
5  Forum 2005-2010 (read only) / Troubleshooting / When programs don't work on: March 17, 2007, 12:17:23 am
I have several times now added a small bit of simple code to a functioning program only to have it stop working or behave strangely. Things as simple as adding one more Serial.println("some debug information") are enough to do it. Adding one more include file even without using it also can doom a functioning program.

The afflicted sketches are still under the 7k size limit, I suspect I might be overflowing RAM.

How would one know they have overflowed RAM? I assume we have a data segment at one end and a stack at the other, I further guess that the data segment must be copied in from the program memory, so there might be a clever binutils command to query the data segment size from the ELF file, but that still leaves stack requirements as a mystery.

Even more basic... I noticed in the bootcloner code a special keyword to make a constant stay in program space. Does the lack of this on our string constants mean they are copied into RAM?

I'll start digging into the generated binaries looking for answers, but any help from people that know would be appreciated.
6  Forum 2005-2010 (read only) / Bugs & Suggestions / Bootloader should clear the watchdog enable bit on: April 19, 2007, 12:50:42 pm
The bootloader should clear the watchdog enable bit, if the fuse hasn't forced it on. This allows sketches to force a reset in software by turning on the watchdog timer and then ignoring it. Very handy if you can't stick your hand where the reset button is.

As long as watchdog code is being touched in the bootloader, it should probably also do a WDR instruction while it loops waiting for characters to keep the timer from going off if it was forced on by the fuses.
7  Forum 2005-2010 (read only) / Bugs & Suggestions / Re: delayclockcycle() on: April 08, 2007, 07:16:11 pm
Yes, you can do such things when time is critical (turn off the interrupts while you are at it). Check the GCC Inline Assembler HOWTO. and the Atmel AVR-8 instruction set.
8  Forum 2005-2010 (read only) / Bugs & Suggestions / Re: delayclockcycle() on: April 04, 2007, 03:00:49 pm
Personally I wouldn't use clock cycles for timing since a clock rate can be changed, except for very small intervals for which rounding is an issue, and then I'm going to need to integrate it with operations around it.

You can't get in and out of a function in much under a microsecond, so if you are looking for better resolution it will need to be inline. For very short delays you can...
__asm__( "nop\n\t"
... for as many nops as you need at one cycle per nop. That could be a significant code size burden for longer delays. If you have a register to spare there are probably two cycle instructions that will make better code density. At some point it is better to loop and count.

If you are needing this sort of resolution, then you will also want to use objdump to disassemble your code and see what the compiler did. It has some amusing reordering rules that can put initialization computations inside your time critical areas.
9  Forum 2005-2010 (read only) / Bugs & Suggestions / Local Libraries on: April 25, 2007, 04:15:21 pm
There should be a place to put libraries that are not part of Arduino distribution. The current scheme makes you lose your libraries when you upgrade, or like me are foolish enough to blow away your library directory to update from the current builds. (Thank you backups.)

I don't know how things are laid out on other platforms, but something like ~/Documents/Arduino/Libraries/ would be convenient for Macs. Add it to the search list for libraries, exclude it from the sketch list. That way all my Arduino code would be in one spot.
10  Forum 2005-2010 (read only) / Bugs & Suggestions / Re: PulseIn - again on: April 24, 2007, 09:17:46 am
The "width * 10" converts from "loops" to clock cycles. The clocksToMicroseconds() converts from clock cycles to microseconds and does the division by 16 or whatever clock rate you declared. (It got renamed since I wrote that, it will be clockCyclesToMicroseconds() by the time it comes out.)

Frustratingly, all though there are a number of clock sources available, the chip appear to only be able to see one for any given fuse configuration. I wanted to make a provision to automatically learn the crystal rate for the various timing conversion functions, but I can't figure out a way to watch one of the slower clocks to count my faster clock cycles.

The serial bootloader could be made to do it by watching the RS232 and performing an autobaud operation, but there isn't room for the code and then I'd have to define a spot in flash or eeprom to hold the result until the sketch was running which would be odd.

(Ok, there is a trick I could do with the watchdog timer to figure out the clock rate, but it seems extreme and is incompatible with people's current bootloader and fuse combinations.)
11  Forum 2005-2010 (read only) / Bugs & Suggestions / Re: PulseIn - again on: April 23, 2007, 11:35:46 pm
The version of pulseIn I sent up for 0008 loses that funny fudge factor. It is using function that aren't in 0007, but I think you can see the timing factors. It is accurate down to 1 (more or less) microsecond.
unsigned long pulseIn(uint8_t pin, uint8_t state)
    // cache the port and bit of the pin in order to speed up the
    // pulse width measuring loop and achieve finer resolution.  calling
    // digitalRead() instead yields much coarser resolution.
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    uint8_t stateMask = (state ? bit : 0);
    unsigned long width = 0; // keep initialization out of time critical area */
    // wait for the pulse to start
    while ( (*portInputRegister(port) & bit) != stateMask)
    // wait for the pulse to stop
    while ( (*portInputRegister(port) & bit) == stateMask)

    // convert the reading to microseconds. The loop has been determined
    // to be 10 clock cycles long and have about 12 clocks between the edge
    // and the start of the loop. There will be some error introduced by
    // the interrupt handlers.
    return clocksToMicroseconds( width * 10 /*clocks/loop*/ +
                                 12 /* approximate clocks from edge to loop*/);
That is calibrated by counting instruction cycles and verified experimentally. As far as a square wave signal generator, you can program the timer 1 and timer 2 channels to put out square waves on digital 9, 10, and 11. Very handy for testing.
12  Forum 2005-2010 (read only) / Bugs & Suggestions / Re: bootloader should use pullup on: April 16, 2007, 09:20:05 pm
The last time I build the bootloader I think there were two spare bytes. But that is enough. I suppose as long as someone might consider touching the bootloader, it would be nice if the programmer 'reset' command was hooked up. Then we wouldn't have to wait for the thing to time out after loading a new sketch. The IDE could just tell it to reboot after the last bit was loaded.
13  Forum 2005-2010 (read only) / Bugs & Suggestions / Support assembly language source files on: April 15, 2007, 01:16:25 pm
For those of us who might be writing a misguided library that requires a fair amount of assembly code, it would be nice if we could have assembly files in our libraries and sketches.

I'm not sure about sketches, but for libraries this little patch works on the principle that gcc knows what to do with a ".S" file. It may have unintended side effects, I'm not sure what the app does in the way of scanning or parsing files.

---        (revision 252)
+++        (working copy)
@@ -260,7 +260,7 @@
     FileFilter onlyCFiles = new FileFilter() {
       public boolean accept(File file) {
-        return (file.getName()).endsWith(".c");
+        return (file.getName()).endsWith(".c") || (file.getName()).endsWith(".S");
     return folder.listFiles(onlyCFiles);
14  Forum 2005-2010 (read only) / Bugs & Suggestions / Re: Large installation on Mac OS X on: March 28, 2007, 03:20:52 pm
Stripping all the binaries works. Executables are found in...
It is safe to just do a "strip *" in those directories. It is smart enough to not butcher the handful of scripts that are in there.
15  Forum 2005-2010 (read only) / Bugs & Suggestions / Re: Large installation on Mac OS X on: March 22, 2007, 02:58:30 pm
I'll check the build process tonight. I haven't built from source yet.
Pages: [1] 2 3 ... 14