Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Re^3: Call function no more than every 0.1 seconds

by jmlynesjr (Deacon)
on Aug 13, 2020 at 01:22 UTC ( #11120672=note: print w/replies, xml ) Need Help??

in reply to Re^2: Call function no more than every 0.1 seconds
in thread Call function no more than every 0.1 seconds

Since I came out of the real-time software world, I would use a processor timer interrupt as you pointed out. However, most of the Arduino world wouldn't understand event driven code if they tripped over it. They use delay() which is blocking - a bad idea.

I participated in the Open Source Ventilator Project in connection with the University of Florida. The Delay() loop people won out and ran off a contributor that had developed an event driven design because they didn't understand it and didn't want to learn. The end result was a working $200 ventilator, out for manufacture, with some really nasty delay() loops. Good luck with maintenance...


There's never enough time to do it right, but always enough time to do it over...

  • Comment on Re^3: Call function no more than every 0.1 seconds

Replies are listed 'Best First'.
Re^4: Call function no more than every 0.1 seconds
by haukex (Bishop) on Aug 13, 2020 at 06:47 UTC
    However, most of the Arduino world wouldn't understand event driven code if they tripped over it. They use delay() which is blocking - a bad idea.

    Heh, true. Arduino does have the advantage of having made microcontrollers more accessible, but at the cost of people not learning as much about the hardware at a lower level.

    I've been working with one lately and I've already run into several issues: that the SD library needs a 512 byte buffer that it apparently allocates dynamically (or at least the complier doesn't detect the need for it, so I manually have to keep an eye on the RAM usage and use globals instead of the stack as much as I can, ugh), that constant strings are stored in RAM, that delay() itself uses interrupts, the low-power library I was using uses the watchdog timer which conflicted with my use of the watchdog... I've learned quite a few things about the libraries by tripping over them.

      The Vent project was based on the Arduino Nano processor as most of the rapid prototype team came out of the Amateur Radio community and were familiar with the Nano from the uBitx SSB transceiver( It was constantly on the edge of running out of RAM and EEPROM. If you get above 70% memory utilization at compile time you stand the chance of seeing a stack overflow at runtime. In the end all the 3rd party libraries were replaced with internal code with the minimal required functionality. Arduino libraries tend to be bloated, blocking, and poorly documented. That said, it's an easy system to learn and works well for personal hobby applications where setup(), loop(), and delay() aren't an issue. It's much more involved to setup a pseudo real-time environment.

      There is a way to tell the compiler to move constant strings into the EEPROM. I'll look it up and get back to you.


      There's never enough time to do it right, but always enough time to do it over...

        The Vent project was based on the Arduino Nano [...]

        That's an ATmega328, 5 V, 16 MHz, 32 KByte Flash ROM, 2 KByte RAM, 8 bit AVR core. It's a nice microcontroller, and it once was impressive.

        Compare to the Arduino Zero:

        ATSAMD21G18, 3.3 V, up to 48 MHz, 256 KByte Flash ROM, 32 KByte RAM, 32 bit ARM Cortex M0+.

        It easily runs circles around the AVR at less power, and you really don't have to worry about memory or CPU speed as much as you have to do with AVR processors.

        Note: This microcontroller was not designed to be fast. It was designed to be cheap and low-power, for battery-powered gadgets, probably running directly from a lithium primary cell (CR2032 or similar). And still, it runs circles around the AVRs. Of course, if you let it run at 48 MHz with no strict power management, it will drain a CR2032 quite fast. But as long as you have a battery pack or mains power, you don't have to worry about power management. It won't get warm or even hot. Your peripherals will most likely need much more power than the SAMD21.

        One obvious problem when migrating projects are the voltage levels: AVRs on Arduino usually run at 5 V. They could run on 3.3 V and even lower, but the AVR core can't run at full speed with lower supply voltages. Or at least, that's what the datasheet said. Maybe it will run at full speed at 3.3 V, but that is out of spec. The SAM needs 3.3 V I/O voltage, the core runs on a much lower voltage (using an integrated LDO regulator). Interfacing CMOS components (any of the 4000 and 4500 series) is usually a no-brainer, they just work as well on 3.3V. The same is true for many IC and SPI components (EEPROMs, ADCs, DACs, port multiplier). When driving bipolar transistors, you may need to reduce the base resistor a little bit. Driving MOSFETS is again often a no-brainer, they are voltage-driven, not current-driven. But you may have to check if the MOSFET actually switches with a gate voltage of only 3.3 V. Some don't.

        Another, closely related problem is the current sink and source capability of the microcontroller. The AVRs can sink or source 40 mA, depending on the Model. The SAMD21 can sink or source only 2 mA, switchable to 7 mA. So if you drive "high" current components directly from AVR pins, you will need some kind of amplification - a transistor, a logic buffer, or (for analog pins) a voltage follower. If you drive an LED directly from a pin, you need to change the series resistor and perhaps have to change the LED for a low-current, high efficency one.

        The SAMD21 does not have an integrated EEPROM. There are some few models that can transparently emulate an EEPROM using a part of the internal flash, but none of them can be found on an Arduino board. But it should be possible to use the self-programming capability of the SAMD21 to manually emulate an EEPROM in the internal flash.

        Comparing the prices:

        At work, we really like the SAMD21, it has retired the ATmega series within weeks. No new project uses ATmegas any more. The SAMD21 needs less power, is faster, has more resources, more peripherals build-in, more I/Os, has up to six highly flexible SERCOMs offering IC, SPI, and USART in a single peripheral, and is cheap. Less than 3.00 for the top-model SAMD21J18A, less than 1.50 for smaller ones.

        Plus, the big Sparkfun breakout board linked above is a really cheap way to prototype a new device, as almost all controller pins are available on pin headers. At less than 30.00 delivered, we even don't care if we kill one of those boards during development. (So far, we have not managed to kill one.) Yes, it lacks the EDBG. But we have plenty of ICE programmers available, so not having an EDBG blocking pins is actually an advantage for us. The smaller Sparkfun board does not bring out all processor pins. Not a big deal for most projects, but sometimes you really want all pins. So we prefer the larger board.

        See also:


        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

        Sorry, I know this is not ArduinoMonks, but to close the loop... From: "Arduino Projects for Amateur Radio" by Jack Purdum, W8TEE (Any book by Jack is an excellent reference)

        The F() Macro

        Suppose you have the following statement in your program code:

            Serial.println("Don't forget to activate all of the external sensors.");

        The message contained within the double quotation marks in the statement is called a string literal. A string literal is a sequence of text characters that does not change as the program executes. These string literals are imbedded in your program's memory space and, hence, do use up Flash memory. The problem is that the compiler sees these string literals and copies them into SRAM just before the program starts executing! In other words, the same string literal is duplicated in Flash and SRAM memory! With the message above, you just wasted 53 bytes of precious SRAM. However, if you change the statement to:

            Serial.println(F("Don't forget to activate all of the external sensors.");

        Note that the string literal is contained within the parentheses of the F() macro. Without going into the mechanics of how this works, the end result is that the F() macro prevents the compiler from copying the string literal to SRAM.


        There's never enough time to do it right, but always enough time to do it over...

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11120672]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2022-01-21 09:16 GMT
Find Nodes?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:

    Results (57 votes). Check out past polls.