Hi all,
I'm running into a problem and I really can't find where it goes wrong.
Trying to make an fuel injector tester and it is actually working ..almost.
first of all I have this code
#include <U8x8lib.h>
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/U8X8_PIN_NONE);
#define BEEPER 8
#define BUTTON_PIN10 10
#define BUTTON_PIN11 11
#define BUTTON_PIN12 12
#define BUTTON_PIN13 13
int i = 0; // counter for "pages"
int pags[5] = { 0, 6, 800, 5, 10 }; // array for page values
String pag[5] = { "PAIRED", "# INJECTORS", "RPM", "DUTY CYCLE %", "TIMER" }; // page titles
int selection = 0; // pointer for walking trough the arrays above
int countdown = 1; // seconds for countdown clock (adjustable)
int countdownCounter = 0; // used to count down :p
unsigned long countdownCounterStart;
int c = 0; // counter for running
int countTill; // copy of c ( devided by 2 (paired))
unsigned long a = 0; // counter that keeps track of openings per injector
unsigned long runTime = 0; // keeps track of (new) time for the global timer
int pinRay[] = { 2, 3, 4, 5, 6, 7 }; // array with pins to drive the injectors
bool pinPower = false; // boolean that stores if a pin is powered (prevents closing injectors multiple times in the loop)
float MPR; // millisecs per revolution (determined by RPM in loop())
float openTime = 0.00; // time an injector is open (determined by MPR and dutyCycle in loop())
//unsigned long nextClosingTime = 0; // time that the open injector must close
float nextClosingTime = 0; // time that the open injector must close
bool running = false; // the sequence is running when true, sequence will stop after all (connected) injectors finished the loop
bool stopCalled = false; // called to kill running
unsigned long lastTimeButtonStateChanged = 0; //debounce start stop btn
bool mayBeep = false; // used to "TIME" the beeper after a timed loop..
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN13, INPUT);
pinMode(BUTTON_PIN12, INPUT);
pinMode(BUTTON_PIN11, INPUT);
pinMode(BUTTON_PIN10, INPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT); //beeper
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.setInverseFont(1);
u8x8.drawString(0, 0, "RagR Builds ");
u8x8.setInverseFont(0);
}
void loop() {
byte buttonState10 = digitalRead(BUTTON_PIN10);
byte buttonState11 = digitalRead(BUTTON_PIN11);
byte buttonState12 = digitalRead(BUTTON_PIN12);
byte buttonState13 = digitalRead(BUTTON_PIN13);
if (pags[0] == 1) { //if paired
MPR = 1000 / ((pags[2] / 2) / 60); //milliSecs Per Revolution
countTill = (pags[1] - 1) / 2;
} else {
MPR = 1000 / (pags[2] / 60); //milliSecs Per Revolution
countTill = pags[1] - 1;
}
openTime = (MPR / 100) * pags[3]; //percent from dutyCycle
/*---------------------------------------------------------------------------------------------------- cycle trough pages--*/
if (buttonState12 == HIGH) {
//pages
i++;
if (i >= 5) {
i = 0;
}
selection = i;
u8x8.setCursor(0, 2);
u8x8.clearLine(2);
u8x8.clearLine(3);
u8x8.clearLine(4);
u8x8.clearLine(5);
u8x8.clearLine(6);
u8x8.println((String)pag[i]);
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
if (i == 4) { // show formatted countdown time
u8x8.println(formatTime(pags[4]));
} else {
u8x8.println((String)pags[i]);
}
delay(250);
}
/*---------------------------------------------------------------------------------------------------- BTN MINUS--*/
if (buttonState10 == HIGH) {
u8x8.clearLine(3);
u8x8.clearLine(4);
//pair injectors (N)
if (i == 0) {
pags[0] = 0;
u8x8.clearLine(3);
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println((String) "not paired");
delay(300);
}
//amountInjectors
if (i == 1) {
pags[1]--;
if (pags[1] <= 1) {
pags[1] = 1;
}
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println((String)pags[i]);
delay(300);
}
//RPM
if (i == 2) {
pags[2] -= 50;
if (pags[2] < 550) {
pags[2] = 550;
}
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println((String)pags[i]);
delay(100);
}
//dutyCycle
if (i == 3) {
pags[3]--;
if (pags[3] <= 1) {
pags[3] = 1;
}
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println(pags[i]);
delay(100);
}
//countdown
if (i == 4) {
pags[4]--;
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println(formatTime(pags[4]));
delay(100);
}
}
/*---------------------------------------------------------------------------------------------------- BTN PLUS--*/
if (buttonState11 == HIGH) {
u8x8.clearLine(3);
u8x8.clearLine(4);
//pairen (Y/N)
if (i == 0) {
if (pags[1] % 2 != 0) {
pags[0] = 0;
u8x8.setCursor(0, 3);
u8x8.clearLine(3);
u8x8.println((String) "cant pair");
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println((String) "odd amount");
} else {
pags[0] = 1;
u8x8.setCursor(0, 4);
u8x8.clearLine(3);
u8x8.clearLine(4);
u8x8.println((String) "paired");
}
}
//amountInjectors
if (i == 1) {
pags[1]++;
if (pags[1] > 6) {
pags[1] = 6;
}
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println((String)pags[i]);
delay(300);
}
//RPM
if (i == 2) {
pags[2] += 50;
if (pags[2] > 7000) {
pags[2] = 7000;
}
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println((String)pags[i]);
delay(100);
}
//dutyCycle
if (i == 3) {
pags[3]++;
if (pags[3] > 100) {
pags[3] = 100;
}
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println((String)pags[i] + " %");
delay(100);
}
//countdown
if (i == 4) {
//both (up/down) btns pressed to generate minuts
if (buttonState10 == HIGH) {
pags[4] += 60;
delay(250);
} else {
pags[4]++;
}
u8x8.setCursor(0, 4);
u8x8.clearLine(4);
u8x8.println(formatTime(pags[4]));
delay(100);
}
}
/*---------------------------------------------------------------------------------------------------- start/stop the sequence --*/
if (millis() - lastTimeButtonStateChanged > 500) {
if (buttonState13 == HIGH) {
lastTimeButtonStateChanged = millis();
if (running) { //pressed STOP during running
stopCalled = true;
Serial.println((String) "pressed stop");
} else {
stopCalled = false;
nextClosingTime = (millis() + openTime);
if (pags[0] == 0) {
Serial.println((String)pinRay[c] + " open: " + millis() + "\tclose: " + nextClosingTime + " (start by btn)");
digitalWrite(pinRay[c], HIGH);
} else { //paired
Serial.println((String)pinRay[c] + " en " + pinRay[c + countTill + 1] + " open: " + millis() + "\tclose: " + nextClosingTime + " (start by btn)");
digitalWrite(pinRay[c], HIGH);
digitalWrite(pinRay[c + countTill + 1], HIGH);
}
pinPower = true;
running = true;
runTime = millis(); //update the timers
countdownCounterStart = millis() + 1000;
countdownCounter = pags[4];
if (a > 0) { //reset the "amount times pulsed" counter"
a = 0;
}
}
u8x8.clearLine(2);
u8x8.clearLine(3);
u8x8.clearLine(4);
u8x8.clearLine(5);
u8x8.clearLine(6);
u8x8.setCursor(0, 2);
u8x8.println((String) "RPM: " + pags[2]);
u8x8.setCursor(0, 3);
u8x8.println((String) "DutyCycle: " + pags[3] + "%");
u8x8.setCursor(0, 4);
u8x8.println((String) "open: " + openTime + "m/s");
u8x8.clearLine(6);
u8x8.setCursor(0, 6);
u8x8.println(formatTime(pags[4]));
}
}
/*----------------------------------------------------------------------------------------------------RUNNING--*/
if (running) {
if (millis() >= (runTime + MPR)) {
nextClosingTime = (millis() + openTime);
runTime += MPR;
//reset loop between injectors & update screen
if (c >= countTill) {
a++; //update amount of loops
u8x8.setCursor(0, 2);
u8x8.println((String) "RPM: " + pags[2]);
u8x8.setCursor(0, 3);
u8x8.println((String) "DutyCycle: " + pags[3] + "%");
u8x8.setCursor(0, 4);
u8x8.println((String) "open: " + openTime + "m/s");
c = 0;
if (stopCalled) {
running = false;
killEmAll();
if (mayBeep) {
beep();
}
}
} else {
c++;
}
if (running) {
if (pags[0] == 1) {
//Serial.println((String)"open double");
Serial.println((String)pinRay[c] + " en " + pinRay[c + countTill + 1] + " open: " + millis() + "\tclose: " + nextClosingTime);
digitalWrite(pinRay[c], HIGH);
digitalWrite(pinRay[c + countTill + 1], HIGH);
} else {
Serial.println((String)pinRay[c] + " open: " + millis() + "\tclose: " + nextClosingTime);
digitalWrite(pinRay[c], HIGH);
}
pinPower = !pinPower;
}
}
//countdown shizzle
if (millis() > countdownCounterStart) {
countdownCounterStart += 1000;
countdownCounter--;
u8x8.setCursor(0, 6);
u8x8.clearLine(6);
u8x8.println(formatTime(countdownCounter));
if (countdownCounter < 1) {
stopCalled = true;
mayBeep = true;
}
}
u8x8.setCursor(0, 5);
u8x8.println((String)a + " loops");
u8x8.setCursor(0, 7);
u8x8.println("press to stop ");
} else {
u8x8.setCursor(0, 7);
u8x8.println("press to start ");
}
// close current injector
if (millis() >= nextClosingTime /*&& running*/ && pinPower) {
if (pags[0] == 1) {
//Serial.println("close double");
Serial.println((String) " " + pinRay[c] + " en " + pinRay[c + countTill + 1] + " dicht: " + nextClosingTime);
digitalWrite(pinRay[c], LOW);
digitalWrite(pinRay[c + countTill + 1], LOW);
} else {
Serial.println((String) "\t" + pinRay[c] + " dicht: " + nextClosingTime);
digitalWrite(pinRay[c], LOW);
}
pinPower = false;
}
} // end loop
void beep() {
digitalWrite(BEEPER, 1);
delay(750);
digitalWrite(BEEPER, 0);
delay(500);
digitalWrite(BEEPER, 1);
delay(750);
digitalWrite(BEEPER, 0);
delay(500);
digitalWrite(BEEPER, 1);
delay(750);
digitalWrite(BEEPER, 0);
countdownCounter = pags[4];
mayBeep = false;
}
//make sure all injectors are closed
void killEmAll() {
for (int k = 0; k < 6; k++) {
Serial.println((String) "kill " + pinRay[k]);
digitalWrite(pinRay[k], LOW);
}
}
//readable time
String formatTime(int timeStamp) {
int cMin = timeStamp / 60;
int cSec = timeStamp % 60;
String e = cSec <= 9 ? "0" : "";
return (String)cMin + ":" + e + cSec;
}
And this is my test enviroment
The code works (opens and close the injectors (leds for now) as long as I keep the RPM under 800 -> int pags[5] = { 0, 6, 800, 5, 10 };
The serial log shows me (when under 800 RPM) perfect open and close times, but when I change to 800 of higher, the first 2 leds/log-lines don't close the current led/injector.
In the next loop it al goes well.
When I really strip the code so there is only a start button and I hardcode the RPM to any number, everything goes well...
Im really searching DAYS now, but really can't find the problem...
The log file now looks like this when 800 or more RPM
2 open: 3435 close: 3438.80 (start by btn)
3 open: 3517 close: 3520.80
4 open: 3603 close: 3606.80
4 dicht: 3606.80
5 open: 3667 close: 3670.80
5 dicht: 3670.80
6 open: 3752 close: 3755.80
6 dicht: 3755.80
7 open: 3817 close: 3820.80
7 dicht: 3820.80
2 open: 3937 close: 3906.80
2 dicht: 3906.80
3 open: 3981 close: 3984.80
3 dicht: 3984.80
4 open: 4045 close: 4048.80
4 dicht: 4048.80
5 open: 4131 close: 4134.80
5 dicht: 4134.80
6 open: 4196 close: 4199.80
6 dicht: 4199.80
7 open: 4281 close: 4284.80
7 dicht: 4284.80
2 open: 4401 close: 4370.80
2 dicht: 4370.80
3 open: 4445 close: 4448.80
3 dicht: 4448.80
pressed stop
4 open: 4559 close: 4562.80
4 dicht: 4562.80
5 open: 4582 close: 4585.80
while it should look like this (example with 750 rpm)
2 open: 76154 close: 76158.15 (start by btn)
2 dicht: 76158.15
3 open: 76258 close: 76262.15
3 dicht: 76262.15
4 open: 76322 close: 76326.15
4 dicht: 76326.15
5 open: 76408 close: 76412.15
5 dicht: 76412.15
6 open: 76494 close: 76498.15
6 dicht: 76498.15
7 open: 76579 close: 76583.15
7 dicht: 76583.15
2 open: 76699 close: 76669.15
2 dicht: 76669.15
3 open: 76743 close: 76747.15
3 dicht: 76747.15
pressed stop
4 open: 76889 close: 76893.15
4 dicht: 76893.15
5 open: 76911 close: 76915.15
5 dicht: 76915.15
6 open: 76997 close: 77001.15
6 dicht: 77001.15
7 open: 77083 close: 77087.15
7 dicht: 77087.15
kill 2
kill 3
kill 4
kill 5
kill 6
kill 7
With the stripped code and change the rpm in the array it works well..
Here is the stripped code I tested (you don't need anything exept one button to test it:
#define BUTTON_PIN10 10
#define BUTTON_PIN11 11
#define BUTTON_PIN12 12
#define BUTTON_PIN13 13
int i = 0; // counter for "pages"
int pags[5] = { 0, 6, 900, 5, 10 }; // array for page values
String pag[5] = { "PAIRED", "# INJECTORS", "RPM", "DUTY CYCLE %", "TIMER" }; // page titles
int selection = 0; // pointer for walking trough the arrays above
int countdown = 1; // seconds for countdown clock (adjustable)
int countdownCounter = 0; // used to count down :p
unsigned long countdownCounterStart;
int cMin;
int cSec;
String e = "0";
int c = 0; // counter for running
int countTill; // copy of c ( devided by 2 (paired))
unsigned long a = 0; // counter that keeps track of openings per injector
unsigned long runTime = 0; // keeps track of (new) time for the global timer
int pinRay[] = { 2, 3, 4, 5, 6, 7 }; // array with pins to drive the injectors
bool pinPower = false; // boolean that stores if a pin is powered (prevents closing injectors multiple times in the loop)
float MPR; // millisecs per revolution (determined by RPM in loop())
float openTime = 0.00; // time an injector is open (determined by MPR and dutyCycle in loop())
//unsigned long nextClosingTime = 0; // time that the open injector must close
float nextClosingTime = 0; // time that the open injector must close
bool running = false; // the sequence is running when true, sequence will stop after all (connected) injectors finished the loop
bool stopCalled = false; // called to kill running
unsigned long lastTimeButtonStateChanged = 0; //debounce start stop btn
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN13, INPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
}
void loop() {
byte buttonState13 = digitalRead(BUTTON_PIN13);
/*---------------------------------------------------------------------------------------------------- start/stop the sequence --*/
if (millis() - lastTimeButtonStateChanged > 500) {
if (buttonState13 == HIGH) {
lastTimeButtonStateChanged = millis();
if (running) { //pressed STOP during running
stopCalled = true;
Serial.println((String) "pressed stop");
} else {
stopCalled = false;
nextClosingTime = (millis() + openTime);
if (pags[0] == 0) {
Serial.println((String)pinRay[c] + " open: " + millis() + "\tclose: " + nextClosingTime + " (start by btn)");
digitalWrite(pinRay[c], HIGH);
} else { //paired
Serial.println((String)pinRay[c] + " en " + pinRay[c + countTill + 1] + " open: " + millis() + "\tclose: " + nextClosingTime + " (start by btn)");
digitalWrite(pinRay[c], HIGH);
digitalWrite(pinRay[c + countTill + 1], HIGH);
}
pinPower = !pinPower;
running = !running;
runTime = millis(); //update the timers
countdownCounterStart = millis() + 1000;
countdownCounter = pags[4];
if (a > 0) { //reset the "amount times pulsed" counter"
a = 0;
}
}
}
}
/*----------------------------------------------------------------------------------------------------RUNNING--*/
//int countTill;
if (pags[0] == 1) { //if paired
MPR = 1000 / ((pags[2] / 2) / 60); //milliSecs Per Revolution
countTill = (pags[1] - 1) / 2;
} else {
MPR = 1000 / (pags[2] / 60); //milliSecs Per Revolution
countTill = pags[1] - 1;
}
openTime = (MPR / 100) * pags[3];
if (running) {
if (millis() >= (runTime + MPR)) {
nextClosingTime = (millis() + openTime);
runTime += MPR;
//reset loop between injectors & update screen
if (c >= countTill) {
c = 0;
if (stopCalled) {
running = !running;
}
} else {
c++;
}
if (running) {
if (pags[0] == 1) {
//Serial.println((String)"open double");
Serial.println((String)pinRay[c] + " en " + pinRay[c + countTill + 1] + " open: " + millis() + "\tclose: " + nextClosingTime);
digitalWrite(pinRay[c], HIGH);
digitalWrite(pinRay[c + countTill + 1], HIGH);
} else {
Serial.println((String)pinRay[c] + " open: " + millis() + "\tclose: " + nextClosingTime);
digitalWrite(pinRay[c], HIGH);
}
pinPower = !pinPower;
}
}
// close current injector
if (millis() >= nextClosingTime && running && pinPower) {
if (pags[0] == 1) {
//Serial.println("close double");
Serial.println((String) " " + pinRay[c] + " en " + pinRay[c + countTill + 1] + " dicht: " + nextClosingTime);
digitalWrite(pinRay[c], LOW);
digitalWrite(pinRay[c + countTill + 1], LOW);
} else {
Serial.println((String) "\t" + pinRay[c] + " close: " + nextClosingTime);
digitalWrite(pinRay[c], LOW);
}
pinPower = !pinPower;
}
}
} // end loop
Does anuone see where I go wrong?
Many thx in advance!!