Hi all from a spanner monkey who is just taking some steps into electronics and programming.
I have been attempting to create a very simple throttle governor for an internal combustion engine using an Arduino Uno, but have run into a snag with my code with which I hope some of you may be able to help me out!
The basic premise of the system I'm hoping to create is that I will be able to use a servo to control the engine throttle, directly onto the carb butterfly. This will be controlled by either one of two modes: "Throttle Mode", in which a potentiometer directly controls the throttle opening. And a "Governing Mode", in which a potentiometer is used to dial a set-speed, and the Arduino compares this set-speed to the actual speed of the engine and matches to two (hopefully using PID control in future iterations).
I have got the basics worked out, I can control servos, read pulses using an interrupt, and read potentiometers into the Arduino. However I am having trouble with what seems to be a conflict between my interrupt and the servo library.
The bug goes something like this:
-
Start system in "throttle mode", everything works fine, servo follows setting on potentiometer.
-
Switch to "governing mode", everything works fine, arduino counts pulses in and reads set-speed and moves servo accordingly.
-
Switch back to "throttle mode", here it goes wrong... Although the serial monitor shows that everything is still working, the servo just does not move any more! As if it is not being given a command.
I hope I have described this adequately, I probably haven't used all the correct terms, this is all still new to me!
I should point out that I'm still prototyping in Tinkercad at the moment, but I don't feel like this is a simulator issue...
Other observations which may be of relevance are that if I comment out everything to do with the servo library and control the servo "manually" by using pinHigh, delay, pinLow, it all works as it should...
Thanks in advance for any help
Here is my code:
// C++ code
//
#include <Servo.h>
int throttlepotpin = A1;
int throttlepotposition;
int govpotpin = A2;
int govpotposition;
int servopin = 3;
int modepin = 4;
int servopulse;
int throttlepotpercent;
int govpotpercent;
int mode;
int targetshaftpulses;
int shaftpulses;
int speedpin = 2;
int error;
Servo servo1;
void setup()
{
pinMode(throttlepotpin, INPUT);
pinMode(govpotpin, INPUT);
pinMode(servopin, OUTPUT);
pinMode(modepin, INPUT);
servopulse = 1500;
pinMode(speedpin, INPUT);
attachInterrupt(digitalPinToInterrupt(2), speed, RISING);
servo1.attach(servopin);
Serial.begin(9600);
}
void loop()
{
delay(20);
mode=digitalRead(modepin);
if (mode==HIGH)
{
govmode();
}
else
{
throttlemode();
}
}
void throttlemode()
{
throttlepotposition=analogRead(throttlepotpin);
servopulse=map(throttlepotposition, 0, 1023, 1000, 2000);
throttlepotpercent=map(throttlepotposition, 0, 1023, 0, 100);
//digitalWrite(servopin, HIGH);
//delayMicroseconds(servopulse);
//digitalWrite(servopin, LOW);
servo1.writeMicroseconds(servopulse);
Serial.print("Throttle mode: ");
Serial.print("Throttle percentage= ");
Serial.print(throttlepotpercent);
Serial.print(" ");
Serial.print(servopulse);
Serial.print('\n');
}
void govmode()
{
//Setting desired speed
govpotposition=analogRead(govpotpin);
targetshaftpulses=map(govpotposition, 0, 1023, 8, 32);
//Seeing what speed is happening
//resetting counters
shaftpulses=0;
//controlling interrupts
interrupts();
//Enables interrupts on the Arduino
delay (20);
//Wait 1/50th second
noInterrupts();
//Disable the interrupts on the Arduino
//Calculating error
error=targetshaftpulses-shaftpulses;
//Controlling servo
servopulse=servopulse+(error*50);
servopulse=constrain(servopulse, 1000, 2000);
servo1.writeMicroseconds(servopulse);
Serial.print("Governing mode: ");
Serial.print("Setspeed=");
Serial.print(targetshaftpulses*125);
Serial.print(" Actual speed=");
Serial.print(shaftpulses*125);
Serial.print(" Error=");
Serial.print(error*125);
Serial.print(" Pulse=");
Serial.print(servopulse);
Serial.print('\n');
}
void speed()
{
shaftpulses++; //The number of pulses in 1/50th of a second
}