help with code for my sequential converter

Hello
My apologies as this is my first adventure into an arduino. I have learned a lot over the last week or so on electronics an programming, but I need some help PLEASE. After trying for many many hours and using different code setups and timers, etc, I have given up and now ask for help. I know many of you are pros and what I am trying to do is simple, but I am learning.

Here is a video I shot using the potentiometer for controll and it seems to work well. .. But I am struggling reading the batch pulse, and converting it into code. Ultimately I need to pull down the 5v for the my readings. Pulses will be very short from 2 to 10 ms, with time between pulses from between 100 down to 10 ms.

I have tried many versions of the code, like below, and I have come very close but doesn't seem to want to keep going. Also I have tried different ways of picking up the pulse... up, down, analog and digital... not getting a consistent signal.

/*
  measuring the the lengh of a pulse and the length between pusles
  then sending the same pulse length to 4 different pins.  
  and deviding the time between pulses over the 4 pins.  
 */
const int pulsePin = 12;
const int ledPin =  13;      // the LED pin for showing incoming pulse
const int lowestPin = A1; 
const int highestPin = A4;
unsigned long duration1;
unsigned long duration2;
int sensorValue = 0;

void setup() {
  // set pins A1 through A4 as outputs:
  for (int thisPin =lowestPin; thisPin <= highestPin; thisPin++)
    pinMode(thisPin, OUTPUT);
  pinMode(pulsePin, INPUT);
}

void loop() {
  // read pulse length:
  duration1 = pulseIn(pulsePin, HIGH);
  duration2 = pulseIn(pulsePin, LOW);
  // add values together to get total cycle:
  sensorValue = (duration1 + duration2);
  // led so for pulse observation:
  digitalWrite(ledPin, HIGH);
  delay(duration1);
  digitalWrite(ledPin, LOW);
  // iterate pulse over the pins:
  for (int thisPin =lowestPin; thisPin <= highestPin; thisPin++) { 
      digitalWrite(thisPin, HIGH);
      delay(duration1);
      digitalWrite(thisPin, LOW);
      delay(sensorValue);
    }
    delay(sensorValue / 4);
}

Sorry, but I am not clear what you want to do. Can you please expand the requirement and explain what your code does not do that you want it to ?

I am trying to convert a quick pulse to ground signal into 4 seperate signals, with the 4 signals being spaced out evenly over the time between the incoming pulses

You are using dealy. This means the processor will miss any pulse sent during that delay, in other words it is blocking. The same goes for your pulse in measurements, that is also blocking.
You need to use the blink without delay technique of using a state machine.

I suggested a general approach to achieve this in your other thread, based on using an interrupt handler to measure the incoming pulse length and a volatile variable to share the result with the main code doing the output pulse timing.

Grumpy_Mike:
You are using dealy. This means the processor will miss any pulse sent during that delay, in other words it is blocking. The same goes for your pulse in measurements, that is also blocking.
You need to use the blink without delay technique of using a state machine.

Oh that makes perfect sense on the delays.... duhhh. Thank you

PeterH:
I suggested a general approach to achieve this in your other thread, based on using an interrupt handler to measure the incoming pulse length and a volatile variable to share the result with the main code doing the output pulse timing.

I appreciate your help, but that is over my head. I am a smart guy but a total beginner at writing this c++ code. Is there any chance you could show me what you mean, or point me to some examples so I could check them out.
I do appreciate the help!! thanks guys!!

I am getting closer
the only problem is if a signal comes in before the cycle is finished, it will miss it and just catchs the next one. How do I correct that?

// Sequential injector firing

const int sensorPin1 = 12;      // input pin for input signal.  It goes to 0 ground to fire 12v saturated injectors
const int sensorPin2 = A0;      // input signal for testing from the potiometer
const int ledPin =  13;
const int InjectorPin1 =  9;    // Output to Injector 1 connected to digital pin 1
const int InjectorPin2 =  2;    // Output to Injector 2 connected to digital pin 2
const int InjectorPin3 =  3;    // Output to Injector 3 connected to digital pin 3
const int InjectorPin4 =  4;    // Output to Injector 4 connected to digital pin 4
const int InjectorPin5 =  5;    // Output to Injector 5 connected to digital pin 5
const int InjectorPin6 =  6;    // Output to Injector 6 connected to digital pin 6
const int InjectorPin7 =  7;    // Output to Injector 7 connected to digital pin 7
const int InjectorPin8 =  8;    // Output to Injector 8 connected to digital pin 8
unsigned long injectTime;       // length of injector pulse
unsigned long cycleTime;        // length of time between injector pulse
long previousMillis = 0;
int inputValue = 0;
int sensorValue = 0;            // used for testing
int betweenValue = 0;           // add togethere inject and cycle for time needed

void setup() {
   pinMode(sensorPin1, INPUT_PULLUP);
   pinMode(sensorPin2, INPUT);
   pinMode(InjectorPin1, OUTPUT);  // initialize the digital pin as an output:
   pinMode(InjectorPin2, OUTPUT);  // initialize the digital pin as an output:
   pinMode(InjectorPin3, OUTPUT);  // initialize the digital pin as an output:
   pinMode(InjectorPin4, OUTPUT);  // initialize the digital pin as an output:
   pinMode(InjectorPin5, OUTPUT);  // initialize the digital pin as an output:
   pinMode(InjectorPin6, OUTPUT);  // initialize the digital pin as an output:
   pinMode(InjectorPin7, OUTPUT);  // initialize the digital pin as an output:
   pinMode(InjectorPin8, OUTPUT);  // initialize the digital pin as an output:
   Serial.begin(9600);
  }

void loop() {
       // read pulse length and cycle length
  inputValue = digitalRead(sensorPin1);
  sensorValue = analogRead(sensorPin2);          //for testing
  cycleTime = pulseIn(sensorPin1, HIGH);          // add values together to get total cycle:
  injectTime = pulseIn(sensorPin1, LOW);
  if (cycleTime > 2200) cycleTime = 16;
  if (injectTime > 200) injectTime = 0;
  betweenValue = (injectTime + cycleTime / 8);
  //injectTime = (sensorValue);              //for testing
  //betweenValue = (sensorValue);        // for testing
  if (inputValue == LOW) {
      cycle();
  
   Serial.println("betweenValue");                 // for testing
   Serial.println(betweenValue);    
   Serial.println("injectTime");    
   Serial.println(injectTime);    
  }
  }
   
void cycle() {
   unsigned long startTime1 = millis();
   while (millis() < startTime1 + injectTime) {
    digitalWrite(InjectorPin1, HIGH);
    //digitalWrite(ledPin, HIGH);
    }  
   digitalWrite (InjectorPin1, LOW);
   //digitalWrite(ledPin, LOW);
   while (millis() < startTime1 + betweenValue) {
     digitalWrite (ledPin, HIGH);
   }
   digitalWrite(ledPin, LOW);
   
   //while (inputValue ==HIGH) {
   unsigned long startTime3 = millis();
   while (millis() < startTime3 + injectTime) {
    digitalWrite(InjectorPin3, HIGH);
    //digitalWrite(ledPin, HIGH);
    }  
   digitalWrite (InjectorPin3, LOW);
   //digitalWrite(ledPin, LOW);
   while (millis() < startTime3 + betweenValue) {
     digitalWrite (ledPin, HIGH);
   }
   digitalWrite(ledPin, LOW);
      
   unsigned long startTime7 = millis();

/////and so on through the 8 injectors in the cycle loop

You don't want to be using pulseIn() to reading the incoming pulse length since this will block your code for a complete cycle. The way to do it is to detect the start and end of each pulse either by polling for status changes or triggering an interrupt handler. At the start of each pulse save the current time. At the end of each pulse subtract the previously saved time from the current time to get the pulse length. If you're doing this in an interrupt handler, the variable holding the pulse length would need to be volatile, and if the variable is bigger than a single byte then you'll need to disable interrupts while accessing it in the main context. The preferred way to do that is to disable interrupts, copy the volatile variable to a temporary local variable and re-enable interrupts, so that interrupts are disabled for the shortest time possible.

The way you're doing time comparisons isn't ideal because it doesn't handle timer overflow correctly. You need to use subtraction rather than addition, i.e.:

while (millis() - startTime1 < betweenValue)

I'm a little surprised you're doing this output with blocking code rather than doing it asynchronously, especially if you want the output events to occur in the background throughout the engine cycle and be able to read the other sensors at regular intervals too.

thanks
and well ... I guess that's because I really have no clue what I am doing with this code :confused: and need haelp

"I'm a little surprised you're doing this output with blocking code rather than doing it , especially if you want the output events to occur in the background throughout the engine cycle and be able to read the other sensors at regular intervals too."

Yes that is what I need, but have no Idea how to do i asynchronously

The pulses are pretty slow in microcontroller terms so you can use the technique in 'blink without delay' to test whether it's time to start or end the next pulse yet. If you're clever, you'll put in other slow operations such as analogRead calls immediately after the pulse output events so you have the maximum time available to complete them before you need to do the next pulse action.

You do also have the option of setting up a hardware timer to do the output for you but that would require more expertise to configure the timer, and write the code to manage pulse timing at varying frequencies and pulse lengths. Doing it in the main context using simple timers would be much easier to get working, even though it'll burn more CPU and you'd hit any performance limits sooner.

I apologize for my code ignorance, but is this what you mean for reading the pulse length.. maybe?
once I have the length of the HIGH and LOW signals read correctly I should be able to run with it from there. I am just struggling to read these without missing some incoming changes. I was looking at the attach interrupts for change and LOW but couldn't get that to work

void loop() {
// read pulse length and cycle length
inputValue = digitalRead(sensorPin1);
sensorValue = analogRead(sensorPin2); //for testing
//betweenValue = (sensorValue); // for testing
if (inputValue == LOW) {
unsigned long startimeTime1 = millis();
while (inputValue == LOW){
digitalWrite(InjectorPin1, HIGH);
digitalWrite(ledPin, HIGH);
}
injectTime = (millis() - startimeTime1);
digitalWrite(InjectorPin1, LOW);
digitalWrite(ledPin, LOW);
}

}

Well that code dosn't do much.
What you must do is to detect just the change in input logic levels not keep doing stuff " while low " because that is blocking code just like delay is. There is a state change example in the IDE.

So when the input changes to say a high make a note of the time in a variable. When it changes to a low subtract the current time form the start time to get the pulse time.

In that way you can measure several pulses at once.

I wrote the demo sketch in the following Thread to show how the Blink Without Delay and State Machine concept can be used to manage several things at once. For another Thread I timed it and the loop repeats after about 47 microseconds so that is probably fast enough to detect the changes in your input pulse without using interrupts.
http://forum.arduino.cc/index.php?topic=223286.0

...R

victor25:
I was looking at the attach interrupts for change and LOW but couldn't get that to work

You're trying to juggle real-time input pulse detection and output pulse generation with background actions like performing analog reads and (presumably) doing map lookups and so on. You could do all of this in the main context by polling the input pulses, but you'd need to manage the scheduling of all this which may not be easy - IMO this is one of the situations where using interrupts to handle the input pulse detection would make sense. In other words, the approach you describe using attachInterrupts. If that isn't working for you I suggest you focus on learning how to do that. I also suggest that you get interrupt based input pulse handling working in isolation and don't complicate the problem with any of the other logic such as generating the output pulses.

ok I completely re-wrote my code to have it call an interrupt on pin 2, but it doesn't seam to do anything. I am using an Arduino Micro this is what it says.

External Interrupts: 0(RX), 1(TX), 2 and 3. These pins can be configured to trigger an interrupt on a low value, a rising or falling edge, or a change in value. See the attachInterrupt() function for details.

I even tried writing something simple to test the port, what am I doing wrong???
could someone please point me in the correct direction here?

int sensorPin = 2;
int led = 13;

void setup() {
pinMode(led, OUTPUT);
pinMode(sensorPin, INPUT_PULLUP);
attachInterrupt(2, injection, LOW);

}

void loop() {
digitalWrite (led, HIGH);
delay(1000);
digitalWrite (led, LOW);
delay(1000);
}

void injection() {
digitalWrite (led, HIGH);
digitalWrite (led, LOW);
}

I completely re-wrote my code to have it call an interrupt on pin 2

I am afraid that is not what you have done.

attachInterrupt() takes an interrupt number not a pin number as its argument, except on a Due. So
  attachInterrupt(2, injection, LOW);is meaningless. What you need is

  attachInterrupt(0, injection, LOW);

So the 0 is not the digital pin number? Then how do I get it watch pin 2? I don't want to use pin 0 or 1 because that's my RX/TX lines.

attachInterrupt(0, injection, LOW);

Attaches the injection function to interrupt 0 which is on pin 2, at least on some, but not all Arduinos
See http://arduino.cc/en/Reference/AttachInterrupt
What board are you using ?