float Kp = 2.0f;
float Ki = 0.5f;
float Kd = 0.1f;
float tau = 10.0f; // было 2.0f, пробуем в тупняк и помехи
float Kplant = 2.5f;
float disturbanceAmp = 50.0f;
const unsigned long dt_ms = 100;
const float dt_s = dt_ms / 1000.0f;
float plantState = 20.0f;
const float ambient = 20.0f; // было 0.5f, пробуем в усиление
float integrator = 0.0f;
float prevMeasured = 0.0f;
static uint32_t rng_state;
void seed_rng() {
uint32_t s = analogRead(A1);
if (s == 0) s = 0x1234567;
rng_state = s;
}
static inline float randf_signed() {
rng_state ^= rng_state << 13;
rng_state ^= rng_state >> 17;
rng_state ^= rng_state << 5;
float v = (rng_state & 0x7FFFFFFF) / 2147483647.0f;
return v * 2.0f - 1.0f;
}
void setup() {
Serial.begin(115200);
seed_rng();
}
int readRawADC() {
return analogRead(A0);
}
float readSetpointFromADC(int raw) {
float denom = (raw > 2000) ? 4095.0f : 1023.0f;
return (raw / denom) * 50.0f; // масштаб 0..50°C
}
float pidCompute(float setpoint, float measured) {
float error = setpoint - measured;
float P = Kp * error;
integrator += error * dt_s;
float I = Ki * integrator;
// ограничение интеграла (anti-windup)
if (I > 100.0f) { I = 100.0f; integrator = I / Ki; }
if (I < -100.0f) { I = -100.0f; integrator = I / Ki; }
float derivative = (measured - prevMeasured) / dt_s;
float D = -Kd * derivative;
prevMeasured = measured;
float out = P + I + D;
if (out > 100.0f) out = 100.0f;
if (out < -100.0f) out = -100.0f;
return out;
}
void updatePlant(float u) {
float disturbance = randf_signed() * disturbanceAmp;
float dy = - (plantState - ambient) / tau + Kplant * (u / 100.0f) + disturbance * 0.1f; // было 0.05f, пробуем в усиление
plantState += dy * dt_s;
}
void loop() {
static unsigned long last = 0;
unsigned long now = millis();
if (now - last < dt_ms) return;
last = now;
int raw = readRawADC();
float sp = readSetpointFromADC(raw);
float meas = plantState;
float u = pidCompute(sp, meas);
updatePlant(u);
// Чтобы все линии имели схожий масштаб, делаем нормализацию raw
float rawScaled = (raw > 2000 ? raw / 4095.0f * 50.0f : raw / 1023.0f * 50.0f);
//Serial.print(rawScaled, 3);
Serial.print(' ');
Serial.print(sp, 3);
Serial.print(' ');
Serial.print(meas, 3);
Serial.print(' ');
Serial.println(u, 3);
}