I made small project with Arduino UNO for my outboard engine TOHATSU 50 2t.
I installed flow sensor (turbine) with Hall effect to measure gasoline flow (consumption) in real time.
Arduino gets the pulses and calculate them into consumed liters, and liters per hour.
Then that information consumed liters and L/h calculated by Arduino are sent via Bluetooth serial communication to my android smart phone that has custom made application made with MIT APP.
In app I put RESET button that should reset counted consumed liters to zero when I press it.
When I power up Arduino, start measuring the consumption, press the reset button on my phone, nothing happen.
But if I press reset button on Arduino (power is always on!), than RESET button start to work.
Can somebody check my code and tell my how to avoid this.
I want that RESET works when Arduino is powered on, I don’t want to press reset button to make it work because Arduino will be installed under engine hood, and it’s not so easy to press the reset on Arduino board.
I’m not great expert in coding and maybe you will find my code chaotic but it works (partially) believe me.
If you have suggestions how to polish it and make it more professional, feel free to shear it.
volatile int PulseCount;
volatile float FlowPulse; //measuring the rising edges of the signal
volatile float RpmPulse; //measuring the rising edges of the signal
float Calc;
float RPMs;
float flowsensor = 2; //The pin location of the sensor
float taho = 3;
int incomingByte;
void setup() {
pinMode(flowsensor, INPUT); //initializes digital pin 2 as an input
pinMode(taho, INPUT);//initializes digital pin 3 as an input
Serial.begin(9600); //This is the setup function where the serial port is initialised,
attachInterrupt(0, rpm, RISING); //and the interrupt is attached
attachInterrupt(1, rps, RISING); //and the interrupt is attached
}
void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
if (incomingByte == 'R') {
PulseCount = 0;
}
}
FlowPulse = 0; //Set NbTops to 0 ready for calculations
RpmPulse = 0;
sei(); //Enables interrupts
delay (4000); //Wait 4 second
cli(); //Disable interrupts
Calc = (FlowPulse * 60 / 127 ); //(Pulse frequency x 60) /30 Q, = 1900/60 * 4 (četri sekundi interval se svodi na 1 sek) flow rate in L/hour
RPMs = (RpmPulse * 10 / 4); // 4 sekundni impulsi sa 6 polnog alternatora svedeni sa 1 sekundu
PulseCount = PulseCount++;
Serial.print(PulseCount);
Serial.print(",");
Serial.print(Calc); //Prints the number calculated above
Serial.print(",");
Serial.print(Calc / incomingByte); //Prints the number calculated above
Serial.print(",");
Serial.print(RPMs);
Serial.println();
}
void rpm () //This is the function that the interupt calls
{
FlowPulse++; //This function measures the rising and falling edge of the hall effect sensors signal
PulseCount++;
}
void rps ()
{
RpmPulse++;
}
PulseCount = PulseCount++ works fine in application, it summarize pulses counted in one loop cycle that last 4 seconds.
That way I count all pulses from time I power my Arduino, and that represent total liters consumed.
If I use only PulseCount++; it will only calculate actual pulses from 4 sec cycle and not sum of all pulses.
Incoming byte should be GPS speed sent from android phone to Arduino.
It doesn’t work so well, but the idea was to get specific consumption in liters per nautical mile.
Arduino calculate liters per hour „calc“ and divide it with MPH that receives from Android APP.
Usually when GPS is not locked and APP doesn’t trigger the speed and 0 is sent to Arduino, result is infinity.
What about reset?
It should reset total liter pulses when it receives incoming Byte „R“ when I press reset button in application.
Instead it works only if I first press reset button on Arduino board and then start counting liters pulses. After that it works fine. Why?
What about reset?
It should reset total liter pulses when it receives incoming Byte „R" when I press reset button in application.
Instead it works only if I first press reset button on Arduino board and then start counting liters pulses. After that it works fine. Why?
Is the blinking light on the HC05 indicating connected status before you press the reset button on the Arduino?
If not, does it show connected after you push it?
cattledog:
Is the blinking light on the HC05 indicating connected status before you press the reset button on the Arduino?
If not, does it show connected after you push it?
Yes! Bluetooth communication is working, otherwise I would not receive any data on my phone.
Also, after I push reset button on Arduino board Bluetooth communication stays connected.
First, fix the undefined behavior issue that Delta G talks about.
Yes! Bluetooth communication is working, otherwise I would not receive any data on my phone.
Are you saying that while the phone is receiving data normally, you try to send a command to the bluetooth module, but it appears not to be received until the hardware rest button is pressed on the Arduino?
cattledog:
First, fix the undefined behavior issue that Delta G talks about.
Are you saying that while the phone is receiving data normally, you try to send a command to the bluetooth module, but it appears not to be received until the hardware rest button is pressed on the Arduino?
Correct!
Only when I press reset on Arduino board things start to work as they should be.
Arduino receive incomingByte „R“ and reset counter to zero.
I fixed error in the code, I removed undefined part "PulseCount = PulseCount++;", but still same problem with reset.
I’m just beginner at coding so I didn’t know that it can work without it.
I’m more like copy/paste/modify little bit and let Arduino compiler check for errors.
That is my programming skill level
volatile int PulseCount;
volatile float FlowPulse; //measuring the rising edges of the signal
volatile float RpmPulse; //measuring the rising edges of the signal
float Calc;
float RPMs;
float flowsensor = 2; //The pin location of the sensor
float taho = 3;
int incomingByte;
void setup() {
pinMode(flowsensor, INPUT); //initializes digital pin 2 as an input
pinMode(taho, INPUT);//initializes digital pin 3 as an input
Serial.begin(9600); //This is the setup function where the serial port is initialised,
attachInterrupt(0, rpm, RISING); //and the interrupt is attached
attachInterrupt(1, rps, RISING); //and the interrupt is attached
}
void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
if (incomingByte == 'R') {
PulseCount = 0;
}
}
FlowPulse = 0; //Set NbTops to 0 ready for calculations
RpmPulse = 0;
sei(); //Enables interrupts
delay (4000); //Wait 4 second
cli(); //Disable interrupts
Calc = (FlowPulse * 60 / 127 ); //(Pulse frequency x 60) /30 Q, = 1900/60 * 4 (četri sekundi interval se svodi na 1 sek) flow rate in L/hour
RPMs = (RpmPulse * 10 / 4); // 4 sekundni impulsi sa 6 polnog alternatora svedeni sa 1 sekundu
Serial.print(PulseCount);
Serial.print(",");
Serial.print(Calc); //Prints the number calculated above
Serial.print(",");
Serial.print(Calc / incomingByte); //Prints the number calculated above
Serial.print(",");
Serial.print(RPMs);
Serial.println();
}
void rpm () //This is the function that the interupt calls
{
FlowPulse++;
PulseCount++;
}
void rps ()
{
RpmPulse++;
}
Thank you for the video. It is a very clear demonstration of the problem.
Which Arduino are you using, and what is the shield attached to it?
It appears that you are plugging the Arduino into a laptop for usb power. Your code indicates that you are using hardware serial for the bluetooth communication.
If you disconnect the bluetooth module, and communicate to the arduino with the serial monitor to send the 'R' do the values reset, or is the hardware reset still required? This might give us a clue.
I'm very unsure about what is going on.
What line ending are you using for the phone transmission?
cattledog:
Thank you for the video. It is a very clear demonstration of the problem.
Which Arduino are you using, and what is the shield attached to it?
It appears that you are plugging the Arduino into a laptop for usb power. Your code indicates that you are using hardware serial for the bluetooth communication.
If you disconnect the bluetooth module, and communicate to the arduino with the serial monitor to send the 'R' do the values reset, or is the hardware reset still required? This might give us a clue.
I'm very unsure about what is going on.
What line ending are you using for the phone transmission?
I use Arduino uno board. Shield is bluetooth plus step down voltage regulator.
The reset start to function only when I manualy reset arduino. After that it works remotely by phone. Watch video again!
It looks like bluetooth must be connected before program start to work.
Im not at home so I cant test serial reset, I will try it later.
Later...
I tried what you suggest, I started Program, spin few pulses, detach Bluetooth shield and send byte R from serial monitor on my PC.
It works, it reset the counter without first resetting Arduino.
Probably problem is somewhere on app side, I will try on MIT App forum.
Thanks for suggestions and help.
Delta_G:
Have you got rid of the undefined behavior yet? You can't really say what it should or should not do as long as that is there.
Yes I did!
See the code.
volatile int PulseCount;
volatile float FlowPulse; //measuring the rising edges of the signal
volatile float RpmPulse; //measuring the rising edges of the signal
float Calc;
float RPMs;
float flowsensor = 2; //The pin location of the sensor
float taho = 3;
int incomingByte;
void setup() {
pinMode(flowsensor, INPUT); //initializes digital pin 2 as an input
pinMode(taho, INPUT);//initializes digital pin 3 as an input
Serial.begin(9600); //This is the setup function where the serial port is initialised,
attachInterrupt(0, rpm, RISING); //and the interrupt is attached
attachInterrupt(1, rps, RISING); //and the interrupt is attached
}
void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
if (incomingByte == 'R') {
PulseCount = 0;
}
}
FlowPulse = 0; //Set NbTops to 0 ready for calculations
RpmPulse = 0;
sei(); //Enables interrupts
delay (4000); //Wait 4 second
cli(); //Disable interrupts
Calc = (FlowPulse * 60 / 127 ); //(Pulse frequency x 60) /30 Q, = 1900/60 * 4 (četri sekundi interval se svodi na 1 sek) flow rate in L/hour
RPMs = (RpmPulse * 10 / 4); // 4 sekundni impulsi sa 6 polnog alternatora svedeni sa 1 sekundu
Serial.print(PulseCount);
Serial.print(",");
Serial.print(Calc); //Prints the number calculated above
Serial.print(",");
Serial.print(Calc / incomingByte); //Prints the number calculated above
Serial.print(",");
Serial.print(RPMs);
Serial.println();
}
void rpm () //This is the function that the interupt calls
{
FlowPulse++;
PulseCount++;
}
void rps ()
{
RpmPulse++;
}
Delta_G:
Code tags. Please. That's really hard to read. Please formatnit and use code tags. If you don't know what that is then read the forum instructions. You should have done that to begin with.
Later...
I tried what you suggest, I started Program, spin few pulses, detach Bluetooth shield and send byte R from serial monitor on my PC.
It works, it reset the counter without first resetting Arduino.
Probably problem is somewhere on app side, I will try on MIT App forum.
Thanks for suggestions and help.
I just noticed this addition to an earlier post. Once you sort out the app/bluetooth situation it would be wise to completely revise you code as Delta G suggest. The format you are using which enables interrupts for a delay() period is one of the worst pieces of code floating around the internet. The flow rate code should looks something like this
volatile unsigned long count = 0;
unsigned long copyCount = 0;
unsigned long lastRead = 0;
unsigned long interval = 1000;//one second
void setup()
{
Serial.begin(115200);
Serial.println("start...");
pinMode(2,INPUT_PULLUP);
attachInterrupt(0, isrCount, RISING); //interrupt signal to pin 2
}
void loop()
{
if (millis() - lastRead >= interval) //read interrupt count every second
{
lastRead += interval;
// disable interrupts,make copy of count,reenable interrupts
noInterrupts();
copyCount = count;
count = 0;
interrupts();
Serial.println(copyCount);
}
}
void isrCount()
{
count++;
}
Nonsense. If you can figure out how to create a complicated Android app with MIT App Inventor, you can figure out how to write correct interrupt based c++ code.
I need delay to get time dependent pulse count.
I use 4 seconds delay to count nuber of pulses that my flowmeter send to Arduino.
Then I use that to calculate liers per hour.
1 liter is 1900 pulse in my case.
4 seconds gives me better average result because carburetors works with float valves, and one second delay give jumping numbers that are anoing. This way I get slower but more precise and consistent consumption.
For the moment this part with interrupts work fine, I see no problems in app.
For sure I will investigate little bit how to polish the code.
I have enoteher question, in my app android phone give GPS speed when location is changed. I would like to sent that infirmation to arduino and than use it to calculate specific consumption in liters per mile by dividing liers per hour (arduino calculate it from hall sens) with miles per hour (arduino should receive fom mit app). So calculated specific consumption arduino will send as serial print to app to display it. Problem is that serial com transforms gps speed (for example 18.65 mph) into ascii and than all math in arduino code goes bad.
Any idea to do this right?
Delta_G:
You don't need a delay to count for four seconds. Use millis like in Blink Without Delay to see the count every four seconds. In that case you only use cli and sei inside that times block when you copy the volatile variables. Same concept either way.
What shell I do with calculations part of the code?
FlowPulse and RpmPulse are volatile variables.
Calc = (FlowPulse * 60 / 127 ); // recalculate flow in L/hour from 4 second FlowPulse
RPMs = (RpmPulse * 10 / 4); // recalculate 4 second 6 pole alternator-tachometer pulses to RPM-s
Code works fine for few seconds, serial print triggers every 4 second, but after that serial print go crazy.
New line of serial print goes fast as hell.
What did I do wrong?
volatile int PulseCount; // counts total pulses coming from tahometer
volatile float FlowPulse; //measuring the rising edges of the signal (flowmetter hall)
volatile float RpmPulse; //measuring the rising edges of the signal(alternator tahometer)
volatile int copyPulseCount; //*** copy counts total pulses coming from tahometer
volatile float copyFlowPulse; //*** copy measuring the rising edges of the signal (flowmetter hall)
volatile float copyRpmPulse; //*** copy measuring the rising edges of the signal(alternator tahometer)
float Calc; // Liters per hour calculation from FlowPulse
float copyCalc; //*** copy
float RPMs; // RPMs calculated from RpmPulse
float copyRPMs; //*** copy
float flowsensor = 2; //The pin location of the flowmeter sensor
float taho = 3; //The pin location of the alternator tahometer
int incomingByte; //serial Byte received from MIT APP
volatile int lastRead = 0; //***
volatile int interval = 4000; //*** 4 second period for counting impulses coming from the sensors
void setup() {
pinMode(flowsensor, INPUT); //initializes digital pin 2 as an input
pinMode(taho, INPUT); //initializes digital pin 3 as an input
Serial.begin(9600); //This is the setup function where the serial port is initialised
attachInterrupt(0, rpm, RISING); //and the interrupt is attached (flowmetter hall)
attachInterrupt(1, rps, RISING); //and the interrupt is attached (alternator tahometer)
}
void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
if (incomingByte == 'R') {
PulseCount = 0;
}
}
if (millis() - lastRead >= interval){ //*** read interrupt count every 4 seconds
lastRead += interval; //***
noInterrupts(); // disable interrupts "cli();"
copyPulseCount = PulseCount; //***
copyFlowPulse = FlowPulse; //***
copyRpmPulse = RpmPulse; //***
FlowPulse = 0; //Set flowmeter pulses to 0 ready for calculations
RpmPulse = 0; //Set alternator tahometer pulses to 0 ready for calculations
interrupts(); // enable interrupts "sei();"
Calc = (copyFlowPulse * 60 / 127 ); // recalculate flow in L/hour from 4 second FlowPulse
RPMs = (copyRpmPulse * 10 / 4); // recalculate 4 second 6 pole alternator-tachometer pulses to RPM-s
Serial.print(copyPulseCount);
Serial.print(",");
Serial.print(Calc); //Prints the number calculated above
Serial.print(",");
Serial.print(RPMs);
Serial.println();
}
}
void rpm () //This is the function that the interupt calls
{
FlowPulse++;
PulseCount++;
}
void rps () //This is the function that the interupt calls
{
RpmPulse++;
}
Code works fine for few seconds, serial print triggers every 4 second, but after that serial print go crazy.
New line of serial print goes fast as hell.
What did I do wrong?
lastRead needs to be typed as unsigned long. It is overflowing after a few additions of the interval value. Only variables changed within the interrupt service routine (isr) need to be typed as volatile.
//volatile int lastRead = 0;
unsigned long lastRead = 0;
Problem is that serial com transforms gps speed (for example 18.65 mph) into ascii and than all math in arduino code goes bad.
Any idea to do this right?
You can use atof() to convert the ascii characters to a float. The ascii values need to be a null terminated c-style string (character array).