Well, I'm out of long shots, it's a very strange problem and I have no idea about what to try next.
I hope you can find out what the problem is and get on with your project.
Anything seems possible when you don't know what you're talking about.
@will I believe I blundered into the solution. I began playing with the size of the LED resistor and found that varying its' size had a profound effect on the interrupt count. If I limit the current to 15 ma, the count is accurate. But higher currents degrade the accuracy very rapidly.
We'll have to see if there is something else I forgot to wire properly before I can feel that it is finally sorted out. But in the meantime, thanks for your help, and to the others who chipped in.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Hi @pratto20,
I am probably reading/interpreting this wrongly, but...
your program says it read your function generator correctly when connected to pin 2 ... but the listing shows 'flow()' connected to '0', as @will noted.
So how did the counting work at that time?
..........
The Arduino Nano lists 20mA drive for I/O pins .. I would expect it to be able to exceed that rating (although I wouldn't you intentionally recommend trying it) without changing functionality, so your observed limit of 15mA is weird.
If you are still suffering from odd behaviour, then I suggest my question, and your other observations, point towards wiring that isn't quite the same as you think. I suggest you carefully check it out, using a meter to 'prove' each of the connections.
Of course the wiring may be totally innocent, but it would be top of my suspects list, and I would want to make sure each wire had a cast iron alibi, as in all the best 'whodunit's. 😀
Good luck, Dave
@pratto20 That is not the solution, that is just a happy coincidence.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
@will This is embarrassing. When I tested it, I had forgotten to move the LED to Pin 8, so no LED was connected to it. As soon as I put the LED in place the LED turned on, and the problem was back.
So I set the Pin back to 6, plugged in the LED and it worked as long as the LED was set LOW, but as so as it went HIGH (and the LED lit up), the problem was back.
So it seems that the problem occurs when the board actually sends current to the LED (not just sets it HIGH), on Pin 6 or 8.
Hi @pratto20, I may be a little late to the party, but I've been monitoring your post, and I believe I have a solution to your problem..First off, The explanation of why you get the correct pulse freq. the first time around is because when the program starts, for some unknown reason , the digitalRead starts in the middle of the pulse period.. this means it is only reading the second rising pulse of the period. this results in the correct count of 88 (88 hz) ..but after that, it starts reading at the start of the pulse, and this results in reading both of the rising pulses in the period..this can be seen in the frizzling drawing below.
The solution to correcting this was to divide the counts by two ( count/2) as shown in the attached code below in a word doc. I included a 10K potentiometer to simulate a 3.7 li-ion battery with a max charge of 4.2 volts ( 42) in the battVoltRaw = map(analogRead(batVolts),0,1023.0, 0, 42); but you can change it to what ever your battery voltage is, just be sure to make it an integer value ..example 37 would represent 3.7, etc, because your dividing it by 10.0 to make it a floating point number..hope this isn't to confusing for you..but it works!.. I'm using a Arduino uno board for testing, because that's what I have.. you Nano board uses the same processor and works the same as the uno, so this should work fine..but in the case it doesn't.. be sure to let me know, so I can do some more research into what is really happening.
the following files will help explain the process a little better ..I hope...lol
good luck with your project,
regards,
LouisR
LouisR
Here is my sketch. I have spent hours trying to sort this out. It's a nice little frequency counter, tho I'm just trying to count pulses from my Water Meter. I am using 1.8.19, on a Nano. It will give me the correct answer the first time thru the loop, but after that the counting is goofed up. My comments at the top give more details. I would appreciate it if anyone would help.
// This sketch runs fine and consistently displays the 88 Hz freq fed in on Pin D2 correctly. // That is, when the digitalWrite() function is commented out. // But if it is not, the first time thru the Flow Rate correctly display shows 88 Hz (from my function generator) // but every loop after that it shows the Water Flow Rate (which is based on the count) in the 700' or 800's. // I put in some Serial.print's to diagnose what is going on. // I think the problem is that while the digitalWrite function is executing, the counter just keeps on rocking, // and I don't know how to make it stop. count = 0 at the bottom doesn't work. I can't get cli()/sei() to work either. // // const byte flowPin = 2; // input from Frq Gen simulating Pulses from Water Flow Meter sensor in garage. int LowVoltageAlarm = 6; // 'time to Replace Battery' LED volatile int flowRate; volatile int count = 0; void setup(){ Serial.begin(19200); // Debugging only pinMode(flowPin, INPUT_PULLUP); // D2 pinMode(LowVoltageAlarm, OUTPUT); digitalWrite(LowVoltageAlarm, LOW); // turn the LED off by setting it LOW attachInterrupt(0, Flow, RISING); // Func Gen input Serial.begin(19200); // Setup Serial Monitor } void Flow() { count++; } void loop() { Serial.print("count1 = "); Serial.println(count); // for diagnostics count = 0; Serial.print("count2 = "); Serial.println(count); delay(1000); Serial.print("count3 = "); Serial.println(count); flowRate = count; Serial.print("count4 = "); Serial.println(count); digitalWrite(LowVoltageAlarm, HIGH); Serial.print("count5 = "); Serial.println(count); Serial.print("Water Flow Rate = "); Serial.print(flowRate); Serial.println(" Pulses/sec"); Serial.print("count6 = "); Serial.println(count); count = 0; Serial.print("count7 = "); Serial.println(count); }
HI,
Just seen your post re external interrupt processing.
Your pin 2 is configured by your sketch with an attendant external interrupt routine which you have defined to trigger on a rising edge pulse.
However, you have defined this pin as INPUT_PULLUP which means its is set high, +5v.
So unless the input attached to pin 2 drops the voltage to 0v when it activates and then it returns to +5v the interrupt will not trigger.
If the attached input however raises the input to +5v on activation then the setting for pin 2 should be defined as INPUT and a 10k ohm pull down resistor should be wired in to ensure the input on pin 2 stays at 0v unless it is raised by the attached componentent.
I am assuming here, of course, that pin 2 can be used for external interrupts on a nano.
Just my thoughts.
Ron B
Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!
@ronbentley1 , Hey Ron...The signal generator that @pratto20 is using is probably doing just that, transitioning from +5 to zero volts, just as mine does.. I my simulator and working circuit, it works just fine, except for the phenomenon of reading the pin 2 input on startup as the correct frequency, and then doubling it on every interval after word. This necessitates dividing the count by 2 to get the correct frequency reading..I'm not 100% sure, but i believe that on startup first time thru, it's reading the pulse in the middle of the period, thus making it only see the end of the period rising pulse. This gives the count of one for the period. The in the subsequent intervals, somehow it syncs up and begins at the start of the period in which now there are two rising pulses.. I've been trying to research this, but so far haven't had any luck finding answer to the problem..The software fix, (divide the count/2) works, and for all the frequencies I tried, both in simulation, and bread board hardware. My test were done on an Arduino uno,
good to see you back on the forum,
regards,
LouisR
LouisR
You're trying to attach an interrupt to pin 0? Is this intentional? I think you should use digitalPinToInterrupt as per the docs at https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/.
@yurkshirelad He has been told that but still.....
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Yeah I thought I'd throw it out there again... 😊
Thanks Louis, yes been away for a while.
I had another look at the sketch following your post (and others).
A number of observations, which support your and other posts:
1. " attachInterrupt(0, Flow, RISING); // Func Gen input" is not correct. It should be:
" attachInterrupt(digitalPinToInterrupt(flowPin), Flow, RISING); // Func Gen input".
Why "0" is specified I cannot fathom!
2. You are correct about the 2 x count value as a complete generator cycle will cause either 2 rising or 2 falling edges, hence two interrupt firings, the "RISING" trigger parameter should be fine with "INPUT_PULLUP".
3. Testing an interrupt volatile variable outside of the interrupt process can cause issues. The interrupt variable "count" is correctly declared as volatile and of type integer (a multi-byte variable). However, the main loop examines and modifies the variable (count) which means that when it is assigned or tested outside of the interrupt process it may not be able to finish a complete read/write cycle before the interrupt triggers again and it is 'corrupted'. The variable "count" is of type integer so is either 2 or 4 bytes in length, hence the potential problem.
This particular issue may be obviated by adding "noInterrupts()" and "Interrupts()" either side of a count test or assignment.
Again, just some observations
Ron B
Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!
@pratto20 et al
Have you ever posted a reply and then something else springs to mind? Yes, of course.
Well, pratto20's sketch troubled me as to the declaration of pin 0 in the attachinterrupt function. I still do not understand why it has been so used, but my further thought is that the use of Serial functions uses pins 0 and 1 by default. What is therefore happening is the the Serial write functions in the main loop are triggering the interrupt and not the input on pin 2 from the external source.
This clearly causes spurious readings.
Regards
Ron B
Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!
Thanks Louis, yes been away for a while.
I had another look at the sketch following your post (and others).
A number of observations, which support your and other posts:
1. " attachInterrupt(0, Flow, RISING); // Func Gen input" is not correct. It should be:
" attachInterrupt(digitalPinToInterrupt(flowPin), Flow, RISING); // Func Gen input".
Why "0" is specified I cannot fathom!
2. You are correct about the 2 x count value as a complete generator cycle will cause either 2 rising or 2 falling edges, hence two interrupt firings, the "RISING" trigger parameter should be fine with "INPUT_PULLUP".
3. Testing an interrupt volatile variable outside of the interrupt process can cause issues. The interrupt variable "count" is correctly declared as volatile and of type integer (a multi-byte variable). However, the main loop examines and modifies the variable (count) which means that when it is assigned or tested outside of the interrupt process it may not be able to finish a complete read/write cycle before the interrupt triggers again and it is 'corrupted'. The variable "count" is of type integer so is either 2 or 4 bytes in length, hence the potential problem.
This particular issue may be obviated by adding "noInterrupts()" and "Interrupts()" either side of a count test or assignment.
Again, just some observations
Ron B
Indeed @ronbentley1, My testing confirms your analysis, and that we are in complete agreement..However, I did try to use "noInterrupts(), and "Interrupts()" as you described but it changed nothing in the count.. One thing I may have forgotten to mention is that it always starts up the same with a correct count , and the the count is double from there on..using a 10k to Pull pin 2 low had no effect on the operation.
Bottom line is the code and frizzle dwg I included in my response to @pratto20 is a working project. The question I have now is why does it always start off only reading one pulse? There's an answer out there somewhere..hehehe Eventually we'll find it..
Thanks for chiming in and giving me some more to think about..
Have a good day,
kind regards,
LouisR
LouisR