Int value servo control and program flow

I am having a problem with programming code to establish a baseline int value from a potentiometer for the initial and default value to monitoring another variable int value for control of a servo.

The project is as follows: I have made an arduino based controller which monitor an electrical signal for Hz frequency. I want to adjust a servo to control the throttle on a generator and maintain a 60 Hz output.

Below is the code I have created but it isnt reliable and is somewhat sluggish. What I am trying to achieve with the code is to take the value of a potentiometer to use as a baseline value and incrementally increase or decrease that value to control a servo based on the value derived from an interupt signal from a digital pin.

In the code you will see reference to 2 different int inputs. I have two pots on the boards and have been experimenting with such. Ideally the second pot signal will control another servo with a different function.

Oh yeah and all of this has to maintain a certain timing for the input signal to be timed or adjusted in the calculation to determine frequency.

All suggestions or advice is appreciated. Here is the code Im working with:


#include <Servo.h>





int vibr_Pin = 7;
int potpin = 0;
int potpin1 = 3;
int potpin2 = 6;
int butval2;
int val;
int val1;  
int val2 = 0;
int val3 = 0;
const int relaygas=A1;
const int relaystart=A2;
int posup=0;
int posup1=0;
int posdn=0;
int posdn1=0;

int vib_data = 0;
volatile byte freqcount;
 int frequency;

unsigned long timeold;
int frequency1;
Servo myservo;
Servo myservo2;
Servo myservo3;

void freq_fun()
 {

  
   //ac cycle, this interrupt function is run twice, so take that into //consideration for 
   //calculating frequency
   //Update count
      freqcount++;}


void setup()
{

  pinMode(vibr_Pin, INPUT); //set vibr_Pin input for measurment
  Serial.begin(9600); //init serial 9600

  Serial.begin(9600);
  
  myservo.attach(3);         // attaches the servo on pin 3 to the //servo object
  myservo2.attach(9);
  myservo3.attach(10);
  
   attachInterrupt(0, freq_fun, FALLING);
   freqcount = 0;
   frequency = 0;
   timeold = 0;

}

void loop() {

intstrt:;{

{val2 = analogRead(A7);            // reads the value of the //potentiometer (value between 0 and 1023)

val2 = map(val2, 0, 1023, 30, 180); // scale it to use it with the //servo (value between 0 and 180)

}
strt:;
Serial.println("starting loop");
//val = map(val2, 0, 1023, 65, 130);
Serial.print("initial POT value");
Serial.println(val2);

myservo.write(val2) ;
delay(10);


val3 = analogRead(A4);            // reads the value of the //potentiometer (value between 0 and 1023)
val3 = map(val3, 1, 1023, 30, 180); // scale it to use it with the //servo (value between 30 and 180)
Serial.print("gas   ");
Serial.println(val3);
posup=val3;

}

//digitalWrite(relaygas, LOW);
// digitalWrite(relaystart, HIGH);

freqchk:;{

// long measurement =TP_init();{
//  delay(50);
//  Serial.print("measurment = ");
//  Serial.println(measurement);
//  if (measurement > 10000){
//  Serial.println("Warning");
//  }
 // else{
   // digitalWrite(LED_Pin, LOW); 
  // Serial.println("Nominal");
 // }
 
 //}
delay(625); 
  Serial.println("delay value");
Serial.println("625");
   
   detachInterrupt(0);
 
    frequency = 60*42 /(millis() - timeold)*freqcount; 
   timeold = millis();
   freqcount = 0;
 
 attachInterrupt(0, freq_fun, FALLING);

   Serial.print("Freq: ");
   frequency1 = frequency/4;
      Serial.print(frequency1);
   Serial.print(" ");
   Serial.print("AC Line Volts: ");
    Serial.println(frequency/1);
 
 
  val = analogRead(A7);
  val = map(val, 0, 1023, 30, 165);
    Serial.println("POT remapping values");
  Serial.println(val);
  Serial.println(val2);
  Serial.println(val3);
  if (val <= 31) {goto intstrt;}
 if (val >= 163) {goto error1;}
  
//freqmap:;{
    Serial.println("Analyzing Freq1 data");
    if (posup >=179) {goto strt;}
    if (posup <=0) {posup=val3;}
     if (frequency1 == 0) {goto systemchk;}
    if (frequency1 == 60) {goto freqchk;}
   
    if (frequency1 <= 40) {goto error1;} 
    if (frequency1 <= 59) {goto up;} 
    if (frequency1 >= 68) {goto error2;}
    if (frequency1 >= 61) {goto dn;}
    
    else Serial.println("error evaluating"); 
   
//}
}

   up:;
   {  Serial.println ("LOW");
 //posup++;
 //posup=(val+posup);
  
   myservo.write(++posup);
   Serial.println(posup);
   goto freqchk;
}
  dn:;

{
   Serial.println ("HIGH");
  //posdn--;
 // posdn=(val-posdn);
     myservo.write(--posup);
     Serial.println(posup);
         goto freqchk;  }


 error1:;
 {
 {Serial.println ("error reset");}
  val = analogRead(A7);
  val = map(val, 0, 1023, 30, 165);
  myservo.write(val);
  delay(50);
 goto strt;
}
 error2:;
{
  {Serial.println ("error master reset");}
 myservo.write(val3);
 //delay(6000);
goto intstrt;
}

systemchk:;{
myservo.write(val3);
delay(500);
Serial.println("system check");
goto freqchk;
}
}
// long TP_init(){
//  delay(10);
//  long measurement=pulseIn (vibr_Pin, HIGH);  //wait for the pin //to get HIGH and returns measurement
//  return measurement;}

We kinda gave up using goto about half a century ago

Please remember to use code tags when posting code.

Sluggish, you say?

intstrt:
strt:
freqchk:
        if (val <= 31) {goto intstrt;}
        if (val >= 163) {goto error1;}
//freqmap:
            if (posup >=179) {goto strt;}
            if (frequency1 == 0) {goto systemchk;}
            if (frequency1 == 60) {goto freqchk;}
            if (frequency1 <= 40) {goto error1;}
            if (frequency1 <= 59) {goto up;}
            if (frequency1 >= 68) {goto error2;}
            if (frequency1 >= 61) {goto dn;}
up:
        goto freqchk;
dn:
        goto freqchk;
error1:
        goto strt;
error2:
        goto intstrt;
systemchk:
        goto freqchk;
  • why delay(625) instead of simply executing the code every so may msec by checking millis()?
  • isn't frequency = freqcount * 1000 / (millis() - timeold);?
  • why de/attahinterrup() instead of [noInterrupts() and interrupts()] (noInterrupts() - Arduino Reference) (2520 = 60*42)

i'm guessing that the error cases are due to some logic problems.

a more conventional approach would be to simply in/decrement some control value, the servo position, depending on if the frequency is above/below some target.

probably some PID code would help to avoid overshoot.

but i think it would be good to develop/confirm a reliable measurement of frequency

lol @ goto. its been that long since i coded anything. ugg. perhaps nonresponsive better describes it as opposed to sluggish

I must presume you to be correct on your suggestions. I am unfortunately not so knowledgable. The code to determine frequency was used from an example provided on a similar samplng for Hz. The 625 is the value that happened to work to provide the expected results when compared to a multimeter testing the hz.

last the 42 I got from researching the sampling of 42 times a second for the audrino processor.

if you could provide an example or links to example i would be greatly appreciative.

The frequency1 check values are the thresholds for action.l 60 being the target hz. 40 is the min to reset board. 59 is the min target. 68 the max threshold and 61 being the max target.

if the interrupt capture N edges in T msec, isn't the frequency simply N * 1000 / T?

i'm also confused why the servo is being set with different variables: posup, val, val2.

if there's a range error, why not simply reset the control variable (i.e. posup)?

i think this is attempting to find a correct starting value. a hardcoded default value should work.

but i believe this is all unnecessary and the result of mis-calculating the frequency as described above and finally

frequency1 = frequency/4;

eager to hear from the OP

yes but the delay in code execution and servo response (they way the current logic flows) changes the 1000 value to maintain accurate timing.

yes I need a starting value but hardcoding the value is limiting and requires the physical linkage to be exact. I was wanting the value to POT adjustable.

Actually I have a lot going on in this project. it may be too much for the arduino nano. I will try to post a schematic of a PCB I had made.

If you don't mind looking at the schematic and advising I would appreciate it.
I have several relays, A nrf24l01 radio, vibration sensor, buzzer, and servos on the PCB. Trying to patch code to tie all of it together. It may be too much.......

here is a link to the schematic

this sounds like the value is determined by trial & error ... it doesn't add up based on my understanding of how the code works.

delays shouldn't affect the frequency calculation if the measurement period is known

You need to redesign your servo power supply, seriously.

What do u suggest ?

It was determined by trial.and error. Im learning that some if not all of the tasks should be defined as functions in the code.

What I do know is execution of the code as currently written definitely affects the timing.

Although eager to learn this language and process function I would be willing to pay someone to code this for me.

please explain the purpose of the circuit and it's various components and inputs

i don't understand how the pins used in the code: pin 3 with a servo and read pins A7 & 15, relate to the schematic

simply printing values for analysis can help better understand what the code is doing

yes i understand. i will prepare a full explanation with reference. i am working on it so plz be patient. thanx.

I was a bit too ambitious in my plans. The architecture of both the code and the components is flawed. A modular approach is best (I think).

Here is what I am doing and trying to achieve. I have a generac 28hp motor which is stepper controlled (unipolar??). I have a 10Kva generator head which will be belt drive by the generac motor.

      (The project started using a 15hp carburated engine and the servo controlled custom PCB and Arduino solution first posted.)

I am trying to achieve these primary functions in order of priority:

  1. Monitoring of AC freq output in Hz. achieved via optocoupler signal to pin D2*.
  2. Control of throttle via stepper motor to maintain 60hz output of generator.
  3. Relay control of gas valve solenoid. Arduino pin D6*.
  4. Relay control of starter solenoid. Arduino pin D5*.
  5. Low oil signal monitoring

*The pin assignment refers to existing Arduino pin assignments

On the custom PCB (which is being revised) I have the following components:

  1. 3 POTs.
  2. Buzzer
  3. 2 relay circuits
  4. 2 Servo ports
  5. L02401 radio
  6. Vibration sensor

I am pretty much scrapping the servo controlled in favor of a stepper controlled solution but hope someone may find this post helpful.

In the revision I would like to incorporate the use of l2401 radio for remote control, vibration sensors to monitor motor/generator health. However it may be best to add those as separate modules which signal back to a remote arduino configuration dedicated to functional group logic.

I have found a thorough post on stepper control throttle with code example I think can be modified for my particular application. I have msg'd the OP of that post to see if he will share the completed code. Here is the link:

I appreciate all input, advice, considerations, comments etc..... positive or negative. Thank you all for contributing thus far.

when developing something new, there may be features or technology that are challenging while others are more common. in such cases, it make sense to prove those challenging features early on.

as already mentioned (post #4), i believe validating a reliable frequency measurement is key