Why use a flag, when you can just use an ATTINY - Page 1
Forum section: electronics / general

author: kolbep
author_rank: Frequent Contributor
timestamp: August 29, 2016, 06:09:12 pm
content: Was having a discussion with somebody today,he is into hobby electronics, and is designing his own Arduino Based GSM Controller (with a Sim module).He is just waiting for his boards to come from China, then he will solder it together, and try it out.One thing he said is that he has a problem, if the Arduino is receiving information (communicating) with the GSM module, and somebody triggers one of the inputs, that it does not do anything to process that trigger.He has not used interrupts before, so I told him that an Interrupt is one way to do it,another way is that while it is receiving / processing data from the GSM Module, he must have a line in that processing loop, that checks if a trigger input was activated, and set a flag. Then once it has finished dealing with the GSM Comms, it can act on that flag (if it is set).He then told me about his solution that he implemented. He 'just' put an ATTINY there to monitor the trigger inputs, and then pass it on to the ATMEGA 328....... So Basically using the ATTINY as a flag variable!Oh Well, Could have saved himself a few rand on each unit.....

author: zapta
author_rank: Super Contributor
timestamp: August 29, 2016, 07:25:16 pm
content: He should learn how to represent his tasks using state machines and polling. A loop that reads an entire line is bad since it holds the CPU.

author: dannyf
author_rank: Super Contributor
timestamp: August 29, 2016, 08:22:24 pm
content: Generally it is a good idea to use interrupts for that kind of tasks.However, it is up to the programmers to implement something he is comfortable with.Having said that, the arduino crowd is generally more interrupt averse.

author: bitseeker
author_rank: Super Contributor
timestamp: August 29, 2016, 10:20:52 pm
content: ATTiny = trigger co-processor

author: wraper
author_rank: Unknown
timestamp: August 29, 2016, 10:30:20 pm
content: You should call him ignorant money burner. Instead of learning a thing he throws the money on the non existing problem.

author: zapta
author_rank: Super Contributor
timestamp: August 29, 2016, 11:40:27 pm
content: Quote from: wraper on August 29, 2016, 10:30:20 pmStill much better than this onehttps://www.eevblog.com/forum/projects/nand-only-freq-counter/

author: obiwanjacobi
author_rank: Super Contributor
timestamp: August 30, 2016, 05:47:39 am
content: That is the spirit of today: use an ARM processor that runs linux (RaspberyPI) to read a humidity sensor...But then again: you cannot fault anyone for not knowing something.He should try make a V2 and fix his mistake. Then he will actually learn something.

author: zapta
author_rank: Super Contributor
timestamp: August 30, 2016, 06:59:33 am
content: He learned using an ATTYNY as a peripheral.

author: Kalvin
author_rank: Super Contributor
timestamp: August 30, 2016, 08:35:01 am
content: Co-opreative, run to completion tasker implementing state machines. Pretty simple and runs very nicely inside Arduino's small Flash and RAM. Easy to debug too as only one "thread" is running at a time.

author: tszaboo
author_rank: Super Contributor
timestamp: August 30, 2016, 09:31:32 am
content: Once I had to capture some microsecond long trigger inputs with an Atmega328. We were only making 5 from this board, I decided to write everything with arduino. I was also an ignorant bum, setting up registers, looking at datasheet, that is no fun.So what I did: I put an RS Flip flop, to capture that trigger, and wasted 3 free GPIO pins, instead of one, and it was like a single EURO cost increase for the company.

author: Kalvin
author_rank: Super Contributor
timestamp: August 30, 2016, 09:46:40 am
content: Capturing the input can be done using polling (in a task implemented as a state machine) or using an interrupt which sets a flag-variable when the input pin changes state to "button pressed".

author: dannyf
author_rank: Super Contributor
timestamp: August 30, 2016, 09:57:27 am
content: Quoteassuming it is a mistake - which i'm not convinced.

author: tszaboo
author_rank: Super Contributor
timestamp: August 30, 2016, 10:05:42 am
content: Quote from: Kalvin on August 30, 2016, 09:46:40 ampolling: trigger too fastinterrupt: boooring!

author: nuno
author_rank: Frequent Contributor
timestamp: August 31, 2016, 02:20:52 am
content: Interrupts are actually not that simple to use for button reading; less problems polling them. Switch bounce can give you interrupt bursts - this is fixable, but by the time you have it fixed, polling would be simpler and easier and have a "deterministic behavior" (including not potentially interfering with other functionality running on the same program).There are other situations where polling is a winner compared to interrupts, usually because of the "interrupt burst" problem.

author: zapta
author_rank: Super Contributor
timestamp: August 31, 2016, 04:08:12 am
content: Quote from: nuno on August 31, 2016, 02:20:52 amYet another example where simple is good.

author: dannyf
author_rank: Super Contributor
timestamp: August 31, 2016, 11:07:34 am
content: "because of the "interrupt burst" problem."For most mcus, that's minor - I think I did a calculation a short while ago and at 1mips that's less than 10 percent of processing power.Pls, RC denounce in my view should always be there.

author: Xenoamor
author_rank: Regular Contributor
timestamp: August 31, 2016, 11:42:30 am
content: You can always make a sample hold analogue circuit.I'm surprised he knows how to figure out interUC communication and control and not interrupts thoughOn a more interesting note though is it possible to have a pin trigger the port interrupt flag setting the interrupt bit BUT not actually trigger an interrupt from it? You could then check the port register for the interrupt bit later and clear it

author: dannyf
author_rank: Super Contributor
timestamp: August 31, 2016, 12:01:17 pm
content: "You can always make a sample hold analogue circuit.I'm surprised he knows how to figure out interUC communication and control and not interrupts though"That's what he seems to be doing. Otherwise, he will have to use the attiny to I terrupt the arduino, which misses the point.

author: dannyf
author_rank: Super Contributor
timestamp: August 31, 2016, 12:03:44 pm
content: "BUT not actually trigger an interrupt from i"Yes. Just don't enable the IOC interrupt. The IOC flag serves as the flag for the pin change event, kind of a software flip flop.Btw, a timer can be configured as an external interrupt or a pcint pin.

author: Xenoamor
author_rank: Regular Contributor
timestamp: August 31, 2016, 12:08:44 pm
content: Quote from: dannyf on August 31, 2016, 12:03:44 pmAwesome thanks. I've always just hopped into the interrupt, set a flag and buggered off. I can see this being useful for time critical stuff though as there's no interrupt priority options

author: KL27x
author_rank: Super Contributor
timestamp: August 31, 2016, 09:08:21 pm
content: QuoteThe problem here is he is using some GPS code that is using interrupt. And he may have downloaded it from somewhere without actually wanting to dig in and modify it.You would have to begin to understand it in order to add any additional interrupt handling that would definitely not interfere with anything timing sensitive. At least figure out how to make his interrupt lower priority. Not that checking a button state takes much time unless u screw up.Of course if his Atmega has pins with IOC flags, he wouldn't even need to do that.If he can redesign a pcb faster than to learn and write any of this new code.... that doesn't mean he is doing it wrong. He could be really great at designing pcbs, lol.Or maybe he wrote all his GPS code, himself. And it is so borked and complicated that it is easier for him to leave it alone and work around it!!!QuoteWhy not? It could be as simple in this case as one pin logic level read and a second line for reset signal. Or even just a read... he could be using the attiny as an array of one shot monostable multivibrators which hold the pin state for greater than the duration of the GPS interrupt.Or... maybe he just used a preexisting arduino routine for I2C?QuoteThere's a right place and time for everything. I recall an example of a faulty remote doorbell used to illustrate this I/O interrupt "problem." Faulty circuit caused the interrupt to retrigger, making the doorbell restart itself, indefinitely, not even finishing the first note of the song. In a case like this, interrupt was probably used to conserve battery power - to wake the ucontroller from sleep state. And the easy solution (for this "problem" would be for the ISR to turn itself off when it is serviced. And for the main program loop to turn it back on.... after the music/chime was over! Of course this doesn't fix the faulty circuit. So now you get to listen to the whole song over and over. So I dunno why this was ever used as an example in the first place.Sometimes, interrupts are going to be a precious commodity for doing things that are wayyy faster and timing sensitive than human input. Sometimes ucontrollers are used to detect a doorbell being pressed.To a lot of us, the button press problem is trivial. And if someone were making 1 million of these things, our knowledge would be valuable. If only these kind of situations were more common. LOL

author: nuno
author_rank: Frequent Contributor
timestamp: August 31, 2016, 11:44:59 pm
content: A button press is not that trivial as an unexperienced person may think the 1st time. It can be debounced in hw, but why add hw when you can do it all in sw? I can think of only the case of very low power or "critical" systems (avoid abrupt transitions on the hw, filtering the input from spikes... but in this case I still think sw deboucing, as add on, is useful as the denouncing timings can be easily adjusted / optimized).Another similar source of interrupt bursts are comparator outputs (many uC have hw filtering to help with this, but each application has its own requirements).Other cases are not that trivial as a button press, such as KL27x's doorbell example. Sometimes the problem is such that the CPU spends too much time servicing (continuous) interrupt bursts. I remember a problem on a system running an embedded realtime linux controlling optical network traffic, with an ASIC raising interrupts for a bunch of events. The system would become unresponsive when the QA guys attenuated the signal to that point where the poor ASIC spent its time changing its decision - signal is ok! no it's not! signal ok! no it's not! and so own (you get the picture). I fixed this one with the "disable interrupt, re-enable sometime later" technique, I couldn't go with polling due to signal loss maximum reaction time requirements.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 01:11:18 am
content: QuoteHow much is too much?

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 01:17:51 am
content: QuoteHere is an example, on a 12f675 but practically identical principle for any other mcu.Code:mcu_init();//initialize the mcuIO_IN(IN_DDR, IN);//in pin as inputIO_SET(WPU, IN); nGPPU = 1;//in with weak pull-upIN_PORT; GPIF = 0;//clear gpifGPIE = 0; IO_SET(IOC, IN);//enable ioc on IN, no interrupt enabled, however.IO_OUT(OUT_DDR, OUT);//out pin as outputwhile (1) {if (GPIF) {//ioc has taken placeIN_PORT; GPIF = 0;//clear the flagIO_FLP(OUT_PORT, OUT);//flip output}delay_ms(100);//waste some time}It sets up IN pin on IN_PORT to enable IOC (interrupt on change) but have the actual interrupt disabled (by clearing GPIE). So there would not be any interrupt when a change of state occurs on the IN pin.In the loop, instead, we poll GPIF to see if a change of state has taken place. If it has, we clear the flag, and then flip a pin.The delay simulates other tasks that you may have in the main loop.If this scheme works, we should expect we should expect a state change to be remembered by the GPIF flag, even if the mcu is busy doing something; once the mcu frees up (in this case, from the delay_ms() routine), it will process the GPIF flag.Here is the simulation, showing exactly the kind of behaviors described above.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 01:21:23 am
content: the basic principle (that a flag will be set even if the corresponding interrupt is disabled) works for other peripherals: for example, the timer flag will be set if the timer overflows, even if the timer interrupt is disabled.This can make some interesting applications.For example, the arduino guy discussed earlier can totally utilize the PCINT or EINT to "remember" the change of state without enabling the respective interrupts, saving him some money with the attiny.

author: KL27x
author_rank: Super Contributor
timestamp: September 01, 2016, 01:51:22 am
content: QuoteThat's archaic. (The hardware, not your code!) Microchip has a lot of new toys on the enhanced midrange.Instead of a single GPIF flag for an entire port,individual rising edge and falling edge flags for each pin on an entire port or three.Individual interrupt enable for each one, rising and/or falling. (Flags are set, whether interrupt is enabled or not).There are many cons, but PIC micros have sweet hardware.QuoteRTOS is using a complicated set of ISR, itself, in order to do its job. Unless you modify these ISR, you cannot prioritize the servicing of your own code. For servicing button interrupt, it is quite possible that it can be done without disruption of even complicated time-dependent ISR. It takes very little execution/processing, but the code has to be written correctly. And another thing that might have fixed this, and which is probably not a bad idea, is to add hysteresis to the good/bad level cutoffs.It wasn't too long ago, microcontrollers were used for mostly such trivial things, to handle RTE without overloading the main CPU. The more complicated the software you run on your micro (and/or the less control you have over it), the more sense it makes to start adding other devices to handle the little stuff.

author: Kalvin
author_rank: Super Contributor
timestamp: September 01, 2016, 06:09:40 am
content: In order to prevent interrupt burst, just use timer interrupt and perform input pin polling and simple filtering in the interrupt service routine in order to set a global flag. Very deterministic and very simple to implement.

author: Kalvin
author_rank: Super Contributor
timestamp: September 01, 2016, 06:21:34 am
content: A simple filter can be implemented using up/down counting or shifting the pin state into a sw shift register.Counter: Sample the pinstate, If the pinstate = 0 and counter > 0 , decrement the counter. If the pinstate = 1 and counter < maximum, increment the counter. When the counter value goes above a "1" threshold, the flag will be set. When the counter value goes below a "0" threshold, the flag will be cleared.Shift register: Update the unsigned uint16 shift register by shiftreg = (shiftreg << 1) | (pinstate & 0x01); if the shiftreg value is 0 clear the flag, if the shiftreg value is 0xffff set the flag.

author: nctnico
author_rank: Super Contributor
timestamp: September 01, 2016, 07:38:22 am
content: Quote from: Kalvin on September 01, 2016, 06:09:40 amThat is the way to do it. In a recent project I had to count the frequency up to 120Hz on 16 digital I/O pins. I used a 10kHz timer interrupt on the highest priority (with nesting) for that purpose and included some signal filtering to get rid of false edges. Using interrupts from I/O pins directly is a catastrophic mistake because it will cause the device to fail at some point with symptoms which are nearly impossible to diagnose.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 01:50:36 pm
content: QuoteEINT tnds to have more specification, as you indicated. PCINT / IOC tend to be much simpler (and should be), as you can implement many of such functionalities in software.Most companies do a good job on EINT/PCINT. The exception is probably ST: the entire ST8/STM32 families have moronic EINT modules in them.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 01:53:19 pm
content: Quoteeach approach is a compromise of a different kind.Polling is deterministic; but wasteful especially if the inputs are rarely asserted;Interrupt is more efficient but not deterministic.Debouncing is a separate problem.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 01:56:21 pm
content: Code:shiftreg = (shiftreg << 1) | (pinstate & 0x01);It is buggy: if pinstate happens to be on anything other than the LSB, it wouldn't work.I would do this:Code:shiftreg = (shiftreg << 1) | (pinstate?0x01:0);with the understanding that pinstate is !0 if asserted.In general, I prefer the counter approach as it is more efficient: you can either reset the counter or decrement the counter when the key fails to assert. shifting is less efficient and more limiting.

author: nuno
author_rank: Frequent Contributor
timestamp: September 01, 2016, 02:27:05 pm
content: Quote from: dannyf on September 01, 2016, 01:11:18 amThe simple answer is: It's too much when it impacts negatively other stuff that needs to be done.Quote from: KL27x on September 01, 2016, 01:51:22 amThere were no buttons to read on that project. Even if we use the lowest possible priority for a button interrupt, I still prefer to poll it, instead of having the interrupt, disabling it and arming a timer etc. I debounce buttons in a very simple way; when a state change is detected, I move to a exclusively time-wait state (50ms is a typical value) and then read the button state and that's it (this also controls the maximum number of button state changes to have per time unit). Button reading is typically the least important thing to do in a project.No hysteresis was support by the hardware on that project, so if one wanted to use interrupts (which one wanted, due to maximum reaction time requirements), one had to deal with it.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 05:24:08 pm
content: QuotePolling certains drains the available processing power thus impacts negatively other stuff that needs to be done. So you wouldn't use polling either?

author: nctnico
author_rank: Super Contributor
timestamp: September 01, 2016, 06:44:55 pm
content: Quote from: dannyf on September 01, 2016, 05:24:08 pmIn most (if not all) cases you'll need to do input filtering in software which basically comes down to sampling (polling) a signal's status. When done cleverly polling doesn't need to take a lot of CPU time.

author: zapta
author_rank: Super Contributor
timestamp: September 01, 2016, 07:23:07 pm
content: Quote from: dannyf on September 01, 2016, 01:53:19 pmPolling and interrupts are not mutually exclusive. For example you can poll in a rubber interrupt.I use interrupts when it provides a clear and useful advantage.

author: Macbeth
author_rank: Super Contributor
timestamp: September 01, 2016, 08:25:57 pm
content: My claim to shame is using an ATtiny85 purely as a monostable multivibrator. It took a bit of telling myself "this is so wrong! total overkill!" but ultimately it was cheaper and used less board space and passive RCs than a conventional 74HC123.

author: nuno
author_rank: Frequent Contributor
timestamp: September 01, 2016, 08:29:28 pm
content: Quote from: dannyf on September 01, 2016, 05:24:08 pmIt is "your application", it's up to you to "decide".Processing power is not the only way to "hurt" some other task.Quote from: zapta on September 01, 2016, 07:23:07 pm+1! And multi-threading too.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 09:11:12 pm
content: QuoteWhat else?

author: nuno
author_rank: Frequent Contributor
timestamp: September 01, 2016, 09:21:10 pm
content: Timing... in a general sense we could add other resources to the "list".

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 09:22:37 pm
content: Quotewhat does that mean?

author: zapta
author_rank: Super Contributor
timestamp: September 01, 2016, 09:52:29 pm
content: Quote from: dannyf on September 01, 2016, 09:11:12 pmover complicated and hard to prove correct code.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 10:17:41 pm
content: QuoteSounds more like an indictment of incompetent programmers.

author: nuno
author_rank: Frequent Contributor
timestamp: September 01, 2016, 10:31:41 pm
content: Quote from: dannyf on September 01, 2016, 09:22:37 pmIt means you have some stuff that really needs to be done at a specific time.Quote from: dannyf on September 01, 2016, 10:17:41 pmIdeally everybody doing embedded programming would excel at programming (anybody doing X should excel at doing X), but what I see in reality is quite different and I just have to live with it.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 10:43:27 pm
content: QuoteWhat happens when you want some stuff to be done while your processor is polling the switch?

author: zapta
author_rank: Super Contributor
timestamp: September 01, 2016, 10:47:37 pm
content: Quote from: dannyf on September 01, 2016, 10:17:41 pmOr a programmer that fits the solution to the overall product lifetime requirements.

author: nuno
author_rank: Frequent Contributor
timestamp: September 01, 2016, 10:48:46 pm
content: Quote from: dannyf on September 01, 2016, 10:43:27 pmDo you have a specific example you want to discuss?

author: Macbeth
author_rank: Super Contributor
timestamp: September 01, 2016, 10:50:50 pm
content: I believe this thread has turned into what is colloquially known as a "Circlejerk"

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 11:01:01 pm
content: QuoteWhy would that make a difference here?

author: zapta
author_rank: Super Contributor
timestamp: September 01, 2016, 11:27:12 pm
content: Quote from: dannyf on September 01, 2016, 11:01:01 pmGood question. Answer is left to the reader.

author: dannyf
author_rank: Super Contributor
timestamp: September 01, 2016, 11:41:48 pm
content: QuoteThat's a poor way of backing up your argument.

author: zapta
author_rank: Super Contributor
timestamp: September 02, 2016, 01:13:06 am
content: Quote from: dannyf on September 01, 2016, 11:41:48 pmNice bait.

author: tszaboo
author_rank: Super Contributor
timestamp: September 02, 2016, 01:08:31 pm
content: Quote from: zapta on September 02, 2016, 01:13:06 amExpected from a troll.

author: nctnico
author_rank: Super Contributor
timestamp: September 02, 2016, 01:17:35 pm
content: Quote from: dannyf on September 01, 2016, 10:43:27 pmUse a higher level interrupt! But still a microcontroller has only time to do X in Y time. So the amount of processing time to do all tasks should always be less. Using interrupts and DMA can be really helpfull but you have to plan resources usage in advance.