Background for the project: using an uno to run a small engine dyno. The dyno monitors a single cylinder briggs and stratton engine (max rpm =3800, idle rpm = 1800), a connected shaft, and eventually force by a lever arm on that shaft. The connected shaft has a 4 tooth sprocket monitored by a PNP proximity sensor.
The arduino then prints these values out on serial, which is picked up by PLX-DAQ. When printing the engine data, it must be proceeded by "DATA", separated by ",".
When I run the code using multiple serial.prints, the code runs okay at low speeds, but loses track at higher speeds ~2200 rpm on either interrupt. This is why I am trying to use one serial.print, thus speeding up the program. I copied my code from an on-board DAQ system that I had previously worked on, and that worked correctly for monitoring the engine and transmission RPMs. Both are attached below
If I try running my dyno code with the sprintf, I am able to see the number of shaft counts, but the rpms are 0. I don't have much programming experience, which is why I am here.
This is the project that I am working on:
// ----------LIBRARIES-------------------------------------------------------------------------------------------------------------
#include "Arduino.h"
// --------CONSTANTS (won't change)--------------------------------------------------------------------------------------------------------------
const int cvtPin = 2; //input pin for proxy sensor
const int enginePin = 3; //input pin for coil rpm
const int lbPin = A3; //input for force sensor
//------------ VARIABLES (will change)--------------------------------------------------------------------------
//CVT
volatile byte CVT_REV = 0; //holds the cvt count while other tasks are happening
unsigned long cvt_time;
unsigned long last_cvt_time;
byte cvt_counts;
int cvt_rpm; //place holder for cvt rpm once calculated
//ENGINE
volatile byte E_REV = 0;
unsigned long engine_time;
unsigned long last_engine_time;
byte e_counts;
int e_rpm;
//FORCE
int lb = 0; //holds force measurement from force sensor
int hp = 0; //holds horsepower based on rpm and lb with a 6.7in torque arm
//TIMING
unsigned long lastMillis = 0; //keeps track of the last time measurements were taken
unsigned long currMillis;
int Update = 1000; //change to update faster or slower NOTE: TIME IS IN MILLISECONDS
char serialBuffer[50] = "";
//=====================================================================
void setup(){
Serial.begin(9600); // the bigger number the better, matches Baud setting in PLX-DAQ
//set up for excell
Serial.println("CLEARDATA"); //clears up any data left from previous projects in PLX-DAQ
Serial.println("LABEL,t (s),Engine RPM,CVT RPM,Power (HP),Torque (in-lbf)"); //always write LABEL, so
//PLX knows the next things will be the names of the columns, seperated by commas
//must be last
attachInterrupt(1, e_count, FALLING); //pin 2 interupt 1
attachInterrupt(0, cvt_count, RISING); //pin 3 interupt 0
}
//=====================================================================
void loop(){
currMillis = millis();
if (currMillis - lastMillis >= Update){ //change update to change resolution, reading too fast might cause the engine to not count
noInterrupts () ;//Disable interrupt when copying
e_counts = E_REV;
E_REV = 0; // Reset the engine REVolution counter
cvt_counts = CVT_REV;
CVT_REV = 0;
interrupts () ; //enable interrupt (interupt #, code to run, when to run it)
e_rpm = (e_counts / (currMillis - lastMillis)); // Convert counts to REV per ms
e_rpm = e_rpm / .0000166; //convert Engine REV per ms to min
cvt_rpm = (cvt_counts / (currMillis - lastMillis)); // Convert counts to REV per ms
cvt_rpm = cvt_rpm / .0000166 /4; //convert Engine REV per ms to min
sprintf(serialBuffer, "DATA, %ld, %d, %d, %d, %d", millis(), e_rpm, e_counts, cvt_rpm, cvt_counts);
Serial.println(serialBuffer);
/* Serial.print(millis());
Serial.print(" , ");
Serial.print(e_rpm);
Serial.print(" , ");
Serial.print(E_REV);
Serial.print(" , ");
Serial.print(cvt_rpm);
Serial.print(" , ");
Serial.println(CVT_REV);
*/
cvt_rpm = 0; //reset the cvt RPM counter
e_rpm = 0; //reset the engine RPM
lastMillis = millis(); //uptade when the last loop occured
}
delay(1); //needs to be here to let the program advance
}
//=====================================================================
void e_count(){
engine_time = micros();
//debounce engine rpm reader
if (engine_time - last_engine_time > 1400) //15873 microseconds @ 3800 rpm
{
E_REV++;
last_engine_time = engine_time;
}
}
//====================================================================
void cvt_count(){
cvt_time = micros();
//decounce rw reader
if (cvt_time - last_cvt_time > 100){
CVT_REV++;
last_cvt_time = cvt_time;
}
}
Here is the project that I copied from:
// ----------LIBRARIES--------------
#include "Arduino.h"
#include <SPI.h>
#include <LiquidCrystal.h>
#include <SD.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
//setup LEDs
#define PIN 4
#define TRANSLED 0
#define CVTLED 1
#define ENGINELED 2
Adafruit_NeoPixel strip = Adafruit_NeoPixel(3, PIN, NEO_RGB + NEO_KHZ800);
// --------CONSTANTS (won't change)---------------
const byte interval = 1000;
//------------ VARIABLES (will change)---------------------
unsigned long lastMillis = 0;
unsigned long currMillis = 0;
//engine vars
volatile byte E_REV = 0;
unsigned long engine_time;
unsigned long last_engine_time;
byte e_counts;
int e_rpm;
//rear wheel vars
volatile byte RW_REV = 0;
unsigned long rw_time;
unsigned long last_rw_time;
byte rw_counts;
int rw_rpm;
void setup() {
Serial.begin(9600); // Open serial communications and wait for port to open
//other set up items
attachInterrupt(0, e_count, FALLING); //pin 2
attachInterrupt(1, rw_count, RISING); //pin 3
}//end setup
void loop() {
currMillis = millis();
if(currMillis - lastMillis >= interval){
//Get RPM
noInterrupts () ;//Disable interrupt when copying
e_counts = E_REV;
E_REV = 0; // Reset the engine REVolution counter
rw_counts = RW_REV;
RW_REV = 0;
interrupts () ; //enable interrupt (interupt #, code to run, when to run it)
e_rpm = (e_counts / (currMillis - lastMillis)); // Convert counts to REV per ms
e_rpm = e_rpm / .0000166; //convert Engine REV per ms to min
rw_rpm = (rw_counts / (currMillis - lastMillis)); // Convert counts to REV per ms
rw_rpm = rw_rpm / .0000166; //convert rear wheel REV per ms to min
//write temps to SD & lcd
SDWrite();
logfile.flush();
char serialBuffer[26] = "";
sprintf(serialBuffer, "%ld,%d,%d,%d,%d,%d,%d", currMillis/1000, rw_rpm, e_rpm, transtemp, cvttemp, etemp, ambtemp);
Serial.println(serialBuffer);
//keep track of time intervals
lastMillis = currMillis;
}
}
void e_count(){
engine_time = micros();
//debounce engine rpm reader
if (engine_time - last_engine_time > 1400) //15873 microseconds @ 3800 rpm
{
E_REV++;
last_engine_time = engine_time;
}
}
void rw_count(){
rw_time = micros();
//decounce rw reader
if (rw_time - last_rw_time > 1400){
RW_REV++;
last_rw_time = rw_time;
}
}
void SDWrite(){//time(s), Rw rpm, engine rpm, transtemp, cvttemp, etemp";
char lineBuffer[24] = "";
sprintf(lineBuffer, "%ld, %d, %d, %d, %d, %d", currMillis/1000, rw_rpm, e_rpm, transtemp, cvttemp, etemp);
logfile.println(lineBuffer);
}