Wpis z mikrobloga

Siema programiści #arduino #diy
Potrzebuję pomocy przy kodzie.
Chcę żeby algorytm PID sterował mi serwomechanizmem. Kod posklejałem z kilku znalezionych w sieci, odczyt napięcia z potencjometru działa, pomiar częstotliwości też działa, sterowanie serwem też działa, problem jest taki że w ogóle PID nie reaguje, jak próbuję odczytać wartość Output na monitorze portu szeregowego to cały czas mam 0.0
Może ktoś przejrzeć kod i podpowiedzieć coś? Wiem że brakuje tam jeszcze tylko nasrać ale to moje 3 podejście do programowania.


#include
#include

//Definicja zmiennych
double Setpoint;
double Input;
double Output;

//Definicja wartosci nastaw dla poszczegolnych czlonow nowe PID
const double Kp = 1;
const double Ki = 0.7;
const double Kd = 0.125;

Servo myservo; // create servo object to control a servo

int Htime; //integer for storing high time
int Ltime; //integer for storing low time
float Ttime; // integer for storing total time of a cycle
float frequency; //storing frequency
float VoltageSensor;
int val; // variable to read the value from the PID
//int STtime;

PID nowePID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);


void setup()
{
Serial.begin(9600); //Inicjalizacja portu szeregowego
pinMode(5,INPUT); //pomiar częstotliwości
pinMode(4,OUTPUT); //Wyjscie pwm

Input = frequency*10;//Inicjalizacja zmiennej Input wartością obliczonej częstotliwości
Setpoint = VoltageSensor; //Wartosc jaka zostaje wprowadzona jako punkt wyzwalania
nowePID.SetMode(AUTOMATIC); //Wlaczenie automatycznego trybu ustawiania wartosci wyjsciowej
nowePID.SetControllerDirection(REVERSE);
myservo.attach(4); // attaches the servo on pin 4 to the servo object
}

void loop()
{
Htime=pulseIn(5,HIGH); //read high time
Ltime=pulseIn(5,LOW); //read low time
Ttime = Htime+Ltime;
//STtime = map(Ttime, 10000, 60000, 0, 1023);
frequency=1000000/Ttime; //getting frequency with Ttime is in Micro seconds
VoltageSensor=analogRead(0);
nowePID.Compute();
analogWrite(4, Output);

val = analogRead(Output);
val = map(val, 0, 1023, 25, 135); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value

//analogWrite(4, Output);

Serial.print("VoltageSensor: ");
Serial.println(VoltageSensor);
Serial.print("Częstotliwość x10: ");
Serial.println(frequency*10);
Serial.print("Output: ");
Serial.println(Output);
// Serial.print("STtime: ");
// Serial.println(STtime);
delay(500);
}
  • 6
@BoKoR: Coś troszkę jaśniej dla laika?
Monitor portu szeregowego cały czas podaje aktualną wartość napięcia i częstotliwości, a wysyłanie tych danych jest w void loop więc wydaje mi się że i PID powinno te dane przyjąć.
@bambus94:
Z chęcią bym pomógł, ale padnięty jestem, więc moje wypociny mogą cię tylko wprowadzić w błąd.

Generalnie w tej linii:

PID nowePID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
określiłeś, że w zmiennej o nazwie Input będziesz przekazywał aktualną wartość do regulatora. Natomiast w Output jest wartość którą powinienieś ustawić na serwo.
W Setpoint ma być wartość którą chcesz aby była ustawiona.

Jak nikt ci nie pomoże, to może uda mi
@BoKoR: Tak, wiem o tym. Problem jest taki, jak przekazać wartość Output z regulatora

analogWrite(4, Output);

do wartości

val = analogRead(Output);


PID chce podać sygnał na konkretny pin, a servo chce pobierać sygnał też z konkretnego pinu. Jak to zrobić żeby informacja z PID trafiła do serva w jak najprostszy sposób?
analogWrite(4, Output);


@bambus94: to jest przepisanie wyjścia PIDa na wyjście analogowe - czy to jest Ci w ogóle potrzebne?
Przecież mogłeś użyć bezpośrednio zmiennej Output

val = analogRead(Output);


a to jest odczyt wartości analogowej z pinu do zmiennej val - tylko że to nie działa, bo parametrem funkcji analogRead powinien być identyfikator pinu, z którego czytasz.

I tak jak kolega Ci napisał, w głównej pętli nie ustawiasz Setpoint ani Input dla