I have now 2 weeks solid in programming a new project, and as a newbie I don't mind figuring out my screwups on my own, but now I have what appears to be stack overflow issues due to the overhead of multiple timing interrupts and sensor pulse input interrupts overloading the processor....so my question is....I need to eliminate the floating point math I threw in....I can't remember the tips I read somewhere about how to avoid floating point where workarounds can be done....fractions in my case will kill the project, what is one to do...
Are you to multiply the parts by say, 100 or 1,000 before multiplying or dividing, to move the fractional part up, then afterwards divide it back down, thus preserving the initial decimal fractional part? Is there more to it?
Thanks as always...
The whole code is too large but here are the 3 interrupt routines and associated calcs needing revision...basically I am calculating flow rate and its average going forward
#include <LiquidCrystal.h>
#include <Time.h> //added to do one second timer
#include <TimeAlarms.h> //added to do one second timer
#include <EEPROM.h>
void setup() {
needed for 1 sec timer
Alarm.timerRepeat(5,Repeats); // timer for every (5) seconds calls Repeats subroutine- upped to 5 due to low counts in a few seconds
Alarm.timerRepeat(3,Toggle); //switch displays while operating
Alarm.timerRepeat(60,ElapsedTime); //increment operating time by one minute while operating
state=0;
lcd.clear();
lcd.begin(16, 2); //rows x cols
lcd.setCursor(0,0);
lcd.print("Fuel Flow Gauge");
Serial.begin(9600);
k_factor = eepromReadInt(9);
delay(5);
lcd.setCursor(0,1);
lcd.print("K-factor is ");
lcd.print(k_factor);
Serial.print("K-factor is ");
Serial.println(k_factor);
delay(1000);
hobbs_hours = eepromReadInt(6); //reads 2 bytes of integer hours
delay(5);
hobbs_minutes = EEPROM.read(8); //reads stored minutes..
delay(5);
lcd.clear();
lcd.print("Hobbs= ");
lcd.print(hobbs_hours,2);
lcd.print(":");
lcd.print(hobbs_minutes,2);
Serial.print("Hobbs stored time is ");
Serial.print(hobbs_hours);
Serial.print(":");
Serial.println(hobbs_minutes);
for (int thisReading = 0; thisReading < numReadings; thisReading++)
readings[thisReading] = 0;
delay(1000);
pinMode(hallsensor, INPUT); //initializes DIGITAL pin 2 as an input
attachInterrupt(0, IncrementFlowPulse, RISING); //and the interrupt is attached
sei(); //go ahead and start counting
}
void IncrementFlowPulse ()
{
total_pulses++ ;
Count++;
tenth_gallon++;
running=1;
}
void Repeats(){
Calc = ((float)Count* ((float)720.0 / (float)k_factor)); //(Counts in 5 seconds/ number counts per gallon, converted from seconds to hours
//using a large value we can select any k-factor - use counts per gallon - perfect
// Calc is the gallons per hour.
if (!flag){ //reset flag so running total flag is run only once
flag=1;} //this is used for averaging routine for average flow rate
if (Count>0){
stopped_flag++; //add 5 seconds to running time length
}
if (stopped_flag>5){
stopped_flag=5;
}
if (Count==0){
stopped_flag--;
}
if (stopped_flag<=0){
stopped_flag=0; // no longer running
}
else { running=1;
}
Count=0; //reset for next interrupt
if ((stopped_flag<=0) && (running) ){
state=10;
return;
}
}
void Toggle(){
if (state==0){
state=1;
return;
}
if (state==1){
state=2;
return;
}
if (state==2){
state=0;
return;
}
}
void ElapsedTime(){
if ((stopped_flag>0) && (running)){
Elapsed_min++;
}
if (Elapsed_min>59){
Elapsed_min=0;
Elapsed_hour++;
return; }
}
void loop ()
{
Alarm.delay(1);
if (flag){
total= total - readings[index];
readings[index] = Calc;
total= total + readings[index];
index++;
if (index >= numReadings)
index = 0;
average = total / (float)numReadings;
delay(1);
}
if ((tenth_gallon) >=(k_factor/10)){
decrement_fuel_level();
tenth_gallon=0; // reset it fro another count
}
switch (state) {
case (0):
state0();
break;
case (1):
state1();
break;
case (2):
state2();
break;
case (6):
state6();
break;
case (7):
state7();
break;
case (8):
state8();
break;
case (9):
state9();
break;
case (10):
state10();
break;
default:
break;
}
}
// end of loop
void state0()
{
lcd.clear();
lcd.noBlink();
lcd.setCursor(0,0);
lcd.leftToRight();
lcd.print (Calc, 2);
lcd.leftToRight();
lcd.setCursor(5,0);
lcd.print ("gal/hr inst");
if (total_pulses ==0){
average=0;
}
lcd.setCursor(5,1);
lcd.print ("gal/hr avg");
lcd.setCursor(0,1);
lcd.leftToRight();
lcd.print (average, 2);
check_keypad(); //see if state has changed via select button
if (key != -1) { //only change value once, don't reset it
a=key;
}
delay(60);
switch (a) {
case 4:
state=6; //go to first menu ...
break;
default: //else do nothing
break;
}
}
if (!flag){ //reset flag so running total flag is run only once
flag=1;} //this is used for averaging routine for average flow rate
Make up your mind. The variable flag is either a boolean or it isn't. If it is, use true or false when assigning it a value. If is isn't, don't treat it like one in an if test.
if (Count>0){
stopped_flag++; //add 5 seconds to running time length
}
How does incrementing stopped_flag add 5 seconds to running time length?
if (Count==0){
stopped_flag--;
}
if (stopped_flag<=0){
stopped_flag=0; // no longer running
}
else { running=1;
}
Has anyone ever told you that your indenting is atrocious? Well, now they have. The Tools + Auto Format menu item sorely needs to be executed.
void Toggle(){
if (state==0){
state=1;
return;
}
if (state==1){
state=2;
return;
}
if (state==2){
state=0;
return;
}
}
void loop ()
{
Alarm.delay(1);
if (flag){
total= total - readings[index];
readings[index] = Calc;
total= total + readings[index];
index++;
if (index >= numReadings)
index = 0;
average = total / (float)numReadings;
delay(1);
}
if ((tenth_gallon) >=(k_factor/10)){
decrement_fuel_level();
tenth_gallon=0; // reset it fro another count
}
switch (state) {
case (0):
state0();
break;
case (1):
state1();
break;
case (2):
state2();
Blank lines galore, and then suddenly everything's jammed together. Is there a reason for that?
Personally, what I see here is a lot of slow writing to a LCD, and yet you want to do away with a few floating point operations in the hopes of speeding up the program. I think you're looking in the wrong place for bottlenecks to deal with.
Thanks for the input, but please keep the insults to a minimum. People come here to learn and get tips and help not passive aggressive putdowns. The formatting got trashed when I pasted it in here...my original coding is 1300 lines and is indented reasonably well, though maybe not to your standards. The pasted mess above looks formatted completely different. Though I have of course a lot to learn, and appreciate the feedback. I will pick up the fixes above and keep truckin'. Though I think what is happening, is when the counts get high due to high flow, stack overflow occurs, and the thing crashes. So I suspect there are still problems....
regarding float of a float, I have been trying all kinds of things to get math to work, didn't catch that the number wasn't converted back to integer.. newbies do that...
Are you to multiply the parts by say, 100 or 1,000 before multiplying or dividing, to move the fractional part up, then afterwards divide it back down, thus preserving the initial decimal fractional part? Is there more to it?
Roughly, sort of. Powers-of-2 are also common. There are minor advantages and disadvantages to each.
but now I have what appears to be stack overflow issues
Unless you are trying to run your program on an ATtiny13 processor I don't see it.
due to the overhead of multiple timing interrupts and sensor pulse input interrupts overloading the processor....
Huh?
Take a step back. Take a deep breath. Describe the symptom(s) rather than what you believe to be the cause.
The reason I suspect stack overflow....there are plenty of places in the code for me to learn and fix things, but it basically works.
When I blow into the flow sensor for testing, I get real world reasonable flow rates, (1-12 gallon per hour) and see the fuel level indicator decrement properly, but if I blow a bit harder, which would simulate when an engine is first started up and fills the fuel line, the rate will jump really high....when I do that, I get trashed values, even the fuel quantity value, which is incremented downward linearly with flow, goes to some unknown silly value, I think it is 655 replacing the unit and tenths digits. Which is why I think the interrupts can't keep up...
The brackets around the zero are not necessary, and are confusing.
now I have what appears to be stack overflow issues due to the overhead of multiple timing interrupts and sensor pulse input interrupts overloading the processor
I only see one interrupt:
attachInterrupt(0, IncrementFlowPulse, RISING); //and the interrupt is attached
3 interrupts...correct, the first and third are pretty simple. The middle one though, has floating point calcs
void IncrementFlowPulse () //This is the function that the flow sensor interrupt on pin 2 calls to add to the count and total count
{
//This function measures the rising and falling edge of the hall effect sensors signal
total_pulses++ ; //change to this variable so running tally is incremented in the background...
Count++;
tenth_gallon++; //be careful here, fuel_tenth and plural exist. this is used to decrement by tenth gallon once it is high enough
running=1;
}
// The setup() runs once, when the sketch starts
// the FOLLOWING loop() method runs over and over again,
// as long as the Arduino has power
//****************************************************************************************
void Repeats(){ //interrupt timer1 repeats every second-changed to 5 seconds...
//here is the math...we sample every 5 seconds. 9200 counts per gallon. FIXED-use float cast to convert integers to float before calculating
Calc = ((float)Count* ((float)720.0 / (float)k_factor)); //(Counts in 5 seconds/ number counts per gallon, converted from seconds to hours
//using a large value we can select any k-factor - use counts per gallon - perfect
// Calc is the gallons per hour.
if (!flag){ //reset flag so running total flag is run only once
flag=1;
} //this is used for averaging routine for average flow rate
if (Count>0){
stopped_flag++; //add 5 seconds to running time length
}
if (stopped_flag>5){ //this is to delay the time till we stop and wait....
//30 seconds or so...it decrements with no flow
stopped_flag=5; //add 5 seconds to length of time running, up to 30 seconds
//-each unit of increase = 5 seconds of stoppage
}
if (Count==0){ //decrement once per 5 second with zero flow...
stopped_flag--;
}
if (stopped_flag<=0){
stopped_flag=0; // no longer running
}
else {
running=1; //added this to ensure it stays running with flow
}
Count=0; //reset for next interrupt
//For some reason, when we start back up from stop, we re-enter the save routine.
if ((stopped_flag<=0) && (running) ){ //we were running, then stopped
state=10; //keeps returning to state 10, stop and save, and looping again
return;
}
}
//****************************************************************************************
void Toggle(){ //this is an interrupt to switch screens every few seconds
if (state==0){
state=1;
return;
}
if (state==1){
state=2;
return;
}
if (state==2){
state=0;
return;
}
}
I sorta wish I had dived into the forum last week, one can learn a lot in a big hurry with such awesome quick feedback.
I just don't want to be any more hassle than one has to be, don't want to be that noob who thinks somebody needs to implant knowledge in his brain without indulging first and learning some the hard way...
Takes about 2.8 uS to execute. So if you do 100 of them you have taken 280 microseconds. Add in the overhead of 100 interrupts, say 5 uS each, and that is another 500 uS. So in total 780 uS.
You have not even used up 1/1000 of the time you have in a second. Time to look elsewhere.
Besides, none of those are floating point variables. I thought you were worried about that?
No actually, it is this interrupt and its floating point math that I jumped to conclusions about...thoug I may simply have more dumb programming mistakes to fix instead.
void Repeats(){ //interrupt timer1 repeats every second-changed to 5 seconds...
//here is the math...we sample every 5 seconds. 9200 counts per gallon. FIXED-use float cast to convert integers to float before calculating
Calc = ((float)Count* ((float)720 / (float)k_factor)); //(Counts in 5 seconds/ number counts per gallon, converted from seconds to hours
//using a large value we can select any k-factor - use counts per gallon - perfect
// Calc is the gallons per hour.
if (!flag){ //reset flag so running total flag is run only once
flag=true;
} //this is used for averaging routine for average flow rate
if (Count>0){
stopped_flag++; //add 5 seconds to running time length
}
if (stopped_flag>5){ //this is to delay the time till we stop and wait....
//30 seconds or so...it decrements with no flow
stopped_flag=5; //add 5 seconds to length of time running, up to 30 seconds
//-each unit of increase = 5 seconds of stoppage
}
if (Count==0){ //decrement once per 5 second with zero flow...
stopped_flag--;
}
if (stopped_flag<=0){
stopped_flag=0; // no longer running
}
else {
running=true; //added this to ensure it stays running with flow
}
Count=0; //reset for next interrupt
//For some reason, when we start back up from stop, we re-enter the save routine.
if ((stopped_flag<=0) && (running) ){ //we were running, then stopped
state=10; //keeps returning to state 10, stop and save, and looping again
return;
}