convert to output pid to speed

i have project lux sensor to move horisontal blind using motor dc and using PID

this my sketch

#include <Wire.h>
#include <BH1750.h>
#include <LiquidCrystal.h>
float error_lux, last1_error, last2_error, P, I, D, Kp = 1.89, Ki = 0, Kd = 0, mv, move, kcptn ;
LiquidCrystal lcd (8, 9, 10, 11, 12, 13);
const int pwm = 3 ;  //initializing pin 2 as pwm
const int in_1 = 5;
const int in_2 = 6;
unsigned long time;
unsigned char move1 = 0;
float setpoint = 140; //setpoint lux


BH1750 lightMeter;


void setup() {
  Serial.begin(9600);
  lightMeter.begin();
  lcd.begin(16, 2);




  pinMode(pwm, OUTPUT) ;
  pinMode(in_1, OUTPUT) ;
  pinMode(in_2, OUTPUT) ;
}



void open (void)
{
  digitalWrite(in_1, LOW ) ;
  digitalWrite(in_2, HIGH) ;

  analogWrite(pwm, ????????) ;
}

void close (void)
{
  digitalWrite(in_1, HIGH ) ;
  digitalWrite(in_2, LOW) ;
 
  analogWrite(pwm, ?????????) ;
}

void stop (void) {
  digitalWrite(in_1, LOW) ;
  digitalWrite(in_2, LOW) ;
  analogWrite(pwm, 0) ;
}

void loop() {


  uint16_t lux = lightMeter.readLightLevel();

  error_lux = setpoint - lux;

  P = Kp * error_lux ;
  I = (Ki * (error_lux + last1_error)) / 2;
  D = (Kd * (error_lux - 2 * last1_error + last2_error)) ;

  mv = P + I + D;


  move = move1 + mv;
  last2_error = last1_error;
  last1_error = error_lux ;




  if (move <= 5 && move >= -5 )
  {
    digitalWrite(in_1, LOW) ;
    digitalWrite(in_2, LOW) ;
    analogWrite(pwm, 0) ;
  }

  else if (move > 5)
  {
    open();
   
  }

  if (move < -5)
  
  {
close();


  }


  time = millis();
  delay(000);
  Serial.print (time);
  Serial.print("\t");
  Serial.println(lux);
  //Serial.print("\t");
  //Serial.println(mv);

}

my motor dc minimum speed is 25

its biderectional when 0 its stop

can someone help me to convert output PID to analog.write my motor dc

thankyouuu

I think you want something like:

#include <Wire.h>
#include <BH1750.h>
#include <LiquidCrystal.h>
float last1_error, last2_error;
const float Kp = 1.89, Ki = 0, Kd = 0;
LiquidCrystal lcd (8, 9, 10, 11, 12, 13);

const int pwm = 3 ;  //initializing pin 3 as pwm
const int in_1 = 5;
const int in_2 = 6;

unsigned long time;
const uint16_t setpoint = 140; //setpoint lux

BH1750 lightMeter;

void setup() {
  Serial.begin(9600);
  lightMeter.begin();
  lcd.begin(16, 2);

  // pinMode(pwm, OUTPUT) ;  // Not needed  analogWrite() takes care of this
  pinMode(in_1, OUTPUT) ;
  pinMode(in_2, OUTPUT) ;
}

void open (byte speed) {
  digitalWrite(in_1, LOW ) ;
  digitalWrite(in_2, HIGH) ;
  analogWrite(pwm, speed) ;
}

void close (byte speed)
{
  digitalWrite(in_1, HIGH ) ;
  digitalWrite(in_2, LOW) ;
  analogWrite(pwm, speed) ;
}

void stop (void) {
  digitalWrite(in_1, LOW) ;
  digitalWrite(in_2, LOW) ;
  analogWrite(pwm, 0) ;
}

void loop() {
  uint16_t lux = lightMeter.readLightLevel();

  float error_lux = setpoint - lux;

  float P = Kp * error_lux ;
  float I = (Ki * (error_lux + last1_error)) / 2;
  float D = (Kd * (error_lux - 2 * last1_error + last2_error)) ;

  float output = P + I + D;

  last2_error = last1_error;
  last1_error = error_lux ;

  if (output > 0) {
    open(constrain(output, 0, 255));
  } else {
    close(constrain(-output, 0, 255));
  }

  time = millis();

  Serial.print(time);
  Serial.print("\tL=");
  Serial.print(lux);
  Serial.print("\tP=");
  Serial.print(P);
  Serial.print("\tI=");
  Serial.print(I);
  Serial.print("\tD=");
  Serial.print(D);
  Serial.print("\tO=");
  Serial.println(output);
  delay(100);
}

johnwasser:
I think you want something like:

#include <Wire.h>

#include <BH1750.h>
#include <LiquidCrystal.h>
float last1_error, last2_error;
const float Kp = 1.89, Ki = 0, Kd = 0;
LiquidCrystal lcd (8, 9, 10, 11, 12, 13);

const int pwm = 3 ;  //initializing pin 3 as pwm
const int in_1 = 5;
const int in_2 = 6;

unsigned long time;
const uint16_t setpoint = 140; //setpoint lux

BH1750 lightMeter;

void setup() {
  Serial.begin(9600);
  lightMeter.begin();
  lcd.begin(16, 2);

// pinMode(pwm, OUTPUT) ;  // Not needed  analogWrite() takes care of this
  pinMode(in_1, OUTPUT) ;
  pinMode(in_2, OUTPUT) ;
}

void open (byte speed) {
  digitalWrite(in_1, LOW ) ;
  digitalWrite(in_2, HIGH) ;
  analogWrite(pwm, speed) ;
}

void close (byte speed)
{
  digitalWrite(in_1, HIGH ) ;
  digitalWrite(in_2, LOW) ;
  analogWrite(pwm, speed) ;
}

void stop (void) {
  digitalWrite(in_1, LOW) ;
  digitalWrite(in_2, LOW) ;
  analogWrite(pwm, 0) ;
}

void loop() {
  uint16_t lux = lightMeter.readLightLevel();

float error_lux = setpoint - lux;

float P = Kp * error_lux ;
  float I = (Ki * (error_lux + last1_error)) / 2;
  float D = (Kd * (error_lux - 2 * last1_error + last2_error)) ;

float output = P + I + D;

last2_error = last1_error;
  last1_error = error_lux ;

if (output > 0) {
    open(constrain(output, 0, 255));
  } else {
    close(constrain(-output, 0, 255));
  }

time = millis();

Serial.print(time);
  Serial.print("\tL=");
  Serial.print(lux);
  Serial.print("\tP=");
  Serial.print(P);
  Serial.print("\tI=");
  Serial.print(I);
  Serial.print("\tD=");
  Serial.print(D);
  Serial.print("\tO=");
  Serial.println(output);
  delay(100);
}

your sketch work to slow down the speed near set point but when pass the setpoint it still void open

because the output didnt get minus value

when 2 lux= output 260

140 lux = output 0

Lux=141.P=123861.15.I=0.00.D=0.00.O=123861.15
Lux=709.P=122787.64.I=0.00.D=0.00.O=122787.64

i didnt get it (cause iam noob and bad english too) your sketch the connection between output and the speed of motor

oh i get it it because const setpoint , i changed it with float setpoint hehehe now it get minus output value

Sorry, the problem happens when lux is greater then setpoint. Both are unsigned so the subtraction causes an overflow. Casting them to signed integers should fix the problem:

  float error_lux = (int)setpoint - (int)lux;

As long as neither is over 32767 (the largest positive value for a signed integer) it should work as expected.