Pulse counting & servo

Hello,

I can not get my program working. I should measure the speed of an engine with pulse counter using following code:

void setup(){
TCCR1A = 0;
TCNT1 = 0;
}

void loop(){
bitSet(TCCR1B, CS12);
bitSet(TCCR1B, CS11);
delay(sampletime);
TCCR1B = 0;
count = TCNT1;
TCNT1 = 0;
}

According to the running speed I should control a servo with code like following:

#include <Servo.h>

Servo myservo;
int position;

void setup(){
myservo.attach(6);
}

void loop(){
myservo.write(position);
}

My pulse counter uses pin 5 and the servo I have attached to pin 6. Individually I can get both programs working but together it only counts pulses, doesn’t rotate the servo.

Is the servo library using the same timer as the pulse counter or what’s the problem?

I really can not understand using interrupts and delay() in the same code.

I have NO idea what you think the code is supposed to do, since there is not a comment to be found. I have no idea what the code actually does, since you didn't say, and, there is no serial output to prove that that is, indeed, what the program is doing.

Is the servo library using the same timer as the pulse counter or what's the problem?

I have some code, lets call it A, that does something. I am not going to tell you what it actually does, or what I expect. Trust me, it works (no magic smoke escapes).

I have some other code that doesn't accomplish anything, either. Lets call that B.

I combined them, but I'm not going to show you that code. The combined code doesn't work. I'm not going to tell you what it actually does. I'm not going to tell you what I expect it to do. I AM going to expect you to tell my why it doesn't work.

So, what is wrong with my code? When you tell me that, I'll tell you what is wrong with your code.

I’m sorry but I deleted the comments because they aren’t written in English and wouldn’t have been understood… I am trying to build a constant RPM controller to the combustion engine. I should read the speed of the engine with Hall-effect sensor (first code, working individually) AND control a servo that pulls the throttle lever.

I can post the original code, of course, (I translated some important parts into English, it’s not my native language):

#include <Servo.h>

Servo myservo;
// Definition of variables and inputs and outputs
const int nopeustietoPin = 5; //the pulse of RPM sensor
const int kytkineteenPin = 10; //switch forward, controller off
const int kytkintaaksePin = 11; //switch backward, resume to previous running speed
const int kytkinalasPin = 12; //switch down, speed decrement of 100 RPM
const int kytkinylosPin = 13; //switch up, speed increment of 100 RPM

const int nayteaika = 1000; //sample time in english
int tila = 0; //state, when 0, controller off, when 1, controller on
int asento; //servo position
int edellinenasetus; //previous RPM setpoint
int pulssimaara; //number of pulses counted in sample time
int virhe; //error
int asetus; //setpoint

void setup() {
  // Definition of pin states and turning on internal pull-ups
  digitalWrite(nopeustietoPin, HIGH); //Sensor reading through a transistor

  pinMode(kytkintaaksePin, INPUT);
  digitalWrite(kytkintaaksePin, HIGH);
  pinMode(kytkineteenPin, INPUT);
  digitalWrite(kytkineteenPin, HIGH);
  pinMode(kytkinalasPin, INPUT);
  digitalWrite(kytkinalasPin, HIGH);
  pinMode(kytkinylosPin, INPUT);
  digitalWrite(kytkinylosPin, HIGH);

  myservo.attach(6);
  
  Serial.begin(9600);

  //Pulse counter formatting
  TCCR1A = 0;
  TCNT1 = 0;
  
}

void loop() {
  
  //Program related to the switch
  while(tila == 0){ //when the controller is off
    bitSet(TCCR1B, CS12);
    bitSet(TCCR1B, CS11);
    delay(nayteaika);
    TCCR1B = 0;
    pulssimaara = TCNT1;
    TCNT1 = 0;
    Serial.println(pulssimaara);
    myservo.write(0); //Servo to extremity when the controller is off
    if(digitalRead(kytkinylosPin) == LOW){ //lever up, controller on
      tila = 1;
      asetus = pulssimaara;
      edellinenasetus = asetus;
    }
    if(digitalRead(kytkinalasPin) == LOW){ //lever down, controller on
      tila = 1;
      asetus = pulssimaara;
      edellinenasetus = asetus;
    }
    if(digitalRead(kytkintaaksePin) == LOW){ //resume to the previous RPM
      tila = 1;
      asetus = edellinenasetus;
    }
  }
  
  while(tila == 1){ //when the controller is on
    bitSet(TCCR1B, CS12);
    bitSet(TCCR1B, CS11);
    delay(nayteaika);
    TCCR1B = 0;
    pulssimaara = TCNT1;
    TCNT1 = 0;
    if(digitalRead(kytkineteenPin) == LOW){ //lever forward, controller off
      tila = 0;
    }
    if(digitalRead(kytkinylosPin) == LOW){ //RPM increment of 100 RPM
      asetus = asetus + 1000; //10 pulses per a revolution of crankshaft
      delay(500); //to prevent uncontrolled speed increment
      edellinenasetus = asetus;
    }
    if(digitalRead(kytkinalasPin) == LOW){ //RPM decrement of 100 RPM
      asetus = asetus - 1000;
      delay(500);
      edellinenasetus = asetus;
    }
    virhe = asetus - pulssimaara; //calculating the error
    if(virhe > 0){ //ajdusting the servo accordingly
      asento = asento + ( virhe * 3 );
      asento = constrain(asento, 0, 180);
    }
    if(virhe <= 0){
      asento = asento + ( virhe * 3 );
      asento = constrain(asento, 0, 180);
    }
    Serial.println(asento);
    myservo.write(asento);
  }
}

I have tried to use this code but it doesn’t work. But I’m able to use the pulse counter and the servo controller individually. My code might be completely wrong but I’m a beginner with Arduino and wrote here to get ideas to implement this kind of system and receive help with my code.

It would also be needful to use a PID controller…

Thank you!

I have tried to use this code but it doesn't work.

"it doesn't work" is NOT the same as "it doesn't do what I want".

The code DOES work. It just doesn't do what you want. You STILL have not told us what it ACTUALLY does, or what you expect it to do.

  // Definition of pin states and turning on internal pull-ups
  digitalWrite(nopeustietoPin, HIGH); //Sensor reading through a transistor

I'd rather see you explicitly define the pin mode (INPUT_PULLUP).

Same for all the other pins.

    Serial.println(pulssimaara);

Anonymous printing sucks. Print some identifier in front of this statement. SHOW US THE OUTPUT.

You are diddling with timers, it appears. Servo uses timer(s). Which one(s) it uses depends on how many there are.

Perhaps you are diddling with the timer that Servo needs. You might have better luck with ServoTimer2.

In addition to what @PaulS has said, it is much too time-consuming to try to figure out what is supposed to happen when values are written to the Timer registers (or any other register). You need to explain in detail what you are trying to do.

...R

Hi,
Welcome to the forum.

Did you google arduino tacho

http://arduinoprojects101.com/arduino-rpm-counter-tachometer/

Can you tell us your electronics, programming, Arduino, hardware experience?

Thanks.. Tom.. :slight_smile:

PaulS:
You STILL have not told us what it ACTUALLY does, or what you expect it to do.

Well, I have told that I'm building a constant RPM controller aka. electronic governor to the combustion engine. Of course, I'm expecting that the system turns the throttle according to the difference between the setpoint and the RPM of the engine. So, I'm expecting that the RPM stays constant and I would be able to adjust the system with a lever consisting four "buttons" (directions told in the comments of the code).

When I try to use it, I can print pulse count and use the lever (have printed state), but the servo certainly doesn't rotate at all as if there was not a PWM signal... However, it's not hardware-related problem because I can control the servo with another code and the same hardware.

You might have better luck with ServoTimer2.

Okay, thanks for factual answer. As I said, I'm a beginner with arduino so I have not idea how to use it. Can I still use a servo library?

Did you google arduino tacho

Yes I did, but writing a code for a tacho ONLY is not a problem even for me. I've actually built a tacho succesfully many times. My problem is controlling a servo at the same time.

Can you tell us your electronics, programming, Arduino, hardware experience?

Yes I can. I understand electronics quite well (studied in the university) but in programming I'm a beginner.

With no doubt building this kind of system with one Arduino Uno is possible. However, I've not been able to find any example codes on the internet.

Can I still use a servo library?

ServoTimer2 IS a servo library. It uses a different timer from the one used by Servo.

Be aware that when you switch to ServoTimer2 the input parameter for servo is in microseconds and not degrees.
There are default minimum and maximum values set by the library.

What do you think, what's the best way to implement this kind of program? I would appreciate all ideas!

What do you think, what's the best way to implement this kind of program?

Remove all the delay() calls. Reconstruct your program using millis() timers. See the "Blink without delay"
example in the ide. Also take a look at the sticky posting at the head of the project guidance section of the forum.

Demonstration code for several things at the same time.

Using the external clock source and Timer1 as a pulse counter is fine.

Now I have rewritten the code using millis() and there is no delays. But there is a problem: if I want to count pulses, there must be a sample time and thus delay() must be used. Or how I could count pulses for example for one second without using delay()?

Store millis() when you start counting, and every time through loop compare that stored millis() to the new one and see if a second has elapsed..

If it has, you have your count per second; if not, go again.

cattledog:
Using the external clock source and Timer1 as a pulse counter is fine.

What do you mean by external clock source? Why can't I use internal clock of the Arduino?

What do you mean by external clock source? Why can't I use internal clock of the Arduino?

Do you have any idea of how your posted sketch is counting pulses?

Why is the pulse of the rpm sensor input on pin 5?
Why are you using this setup for the clock source/prescaler?

bitSet(TCCR1B, CS12);
    bitSet(TCCR1B, CS11);

Mindless copy and paste is not a good way to develop programming skills.

cattledog:
Do you have any idea of how your posted sketch is counting pulses?

I don’t perfectly understand yet, but I think that bitSet(TCCR1B, CS12); starts counting pulses and bitSet(TCCR1B, CS11); clocks rising edges.

Why are you using this setup for the clock source/prescaler?

It’s the only I’ve learned to use. I’ve not found a better option, but if you know one, tell me!

Mindless copy and paste is not a good way to develop programming skills.

I agree!

What do you mean by external clock source? Why can't I use internal clock of the Arduino?

You are using Timer1 as a counter and it counts +1 every time it sees a falling edge of the input pulse on pin 5. When the timer counts based on an external input like that, it is said to be using an external clock source.

If it were counting on the Arduino internal clock source it would be +1 every clock cycle of the processor.

You are still using the Arduino's internal clock for everything else but incrementing Timer1.

I don't perfectly understand yet, but I think that bitSet(TCCR1B, CS12); starts counting pulses and bitSet(TCCR1B, CS11); clocks rising edges.

Not exactly. Setting those 2 bits in the prescaler group, instructs the timer to use an external clock source on pin 5 and to count of the falling edge. The count on rising edge of the external clock source signal is selected by

 bitSet(TCCR1B, CS12);
 bitSet(TCCR1B, CS11);
 bitSet(TCCR1B, CS10);

All these things are explained in the data sheet for the AT328. You should be referring to this data sheet if you are going to be getting into the timers like you are.

Finland:

Mindless copy and paste is not a good way to develop programming skills.

I agree!

On the other hand, copying code from somewhere and then spending time trying to understand it in conjunction with the Atmega 328 datasheet is a good way to develop skills.

...R