PWM/ RPM feedback loop

Hey,
so I need some help. Ive got this project that im working on that goes like this: Im creating a set up that reads light sensor values and adjusts a motors speed accordingly using an arduino and a L293D motor controller. Heres the catch, Im using an oscilloscope to look at my RPM as well as diplaying my RPM through the serial monitor. Im trying to create a feedback loop that looks at the error and adjust accordingly. Im not really sure how to go about this.
I have tried to do something that compares the RPM goal (based off what the light sensor reads) with the RPM calculated from the PulseIn. If they are not equal, it either adds or subtracts from the PMW value getting sent to the decoder. This is not seeming to work however. Any ideas?
Heres the current code.

int pulse=A0;
float microT=0;
float T=0;
float RPMm=0;
float RPMs=0;
int sensorpin=A1;
int sensorvalue;
int sensorscale;

void setup() {
Serial.begin(9600);
pinMode(A0,INPUT);
pinMode(5, OUTPUT);
}

void loop() {

sensorvalue=analogRead(sensorpin);
sensorvalue=map(sensorvalue,0,1023,0,255);
analogWrite(5,sensorvalue);
microT=pulseIn(pulse, HIGH);
T=microT*.0000012;
RPMm=60/(16
T);
RPMs=(RPMm/30);
Serial.println(RPMs);
delay(250);
}

Im trying to create a feedback loop that looks at the error and adjust accordingly. Im not really sure how to go about this.

Maybe by using the PID library

What is the value from the light sensor when you want the motor to stop? Surely not zero?

What is the value from the light sensor when you want the motor to drive at maximum speed?

Put those 2 values into the 2nd and 3rd arguments to the map() function. Adjust as necessary until it runs right.

You need to explain more clearly what sort of light sensor you are using and how its output relates to the speed of your motor.

I use a QRE1113 reflective optical sensor that produces one pulse for each revolution of a small DC motor. The code I use to measure the speed is similar to this - it's not complete but should give the idea

volatile unsigned long isrMicros;
unsigned long latestIsrMicros;
unsigned long previousIsrMicros;
volatile boolean newISR = false;

void loop() {
   if (newISR == true) {
     previousIsrMicros = latestIsrMicros; // save the old value
     noInterrupts(); // pause interrupts while we get the new value
        latestIsrMicros = isrMicros;
        newISR = false;
     interrupts();
     microsThisRev = latestIsrMicros - previousIsrMicos;
}

void myISR() {
   isrMicros = micros();
   newISR = true;
}

I then use PID (actually just PI) to keep the speed at a chosen rate.

...R

a snippet to write your own PID controller

/*
output = Kp * err + (Ki * Ierr * dt) + (Kd * Derr /dt);
where

Kp = Proptional Constant.
Ki = Integral Constant.
Kd = Derivative Constant.
err = Expected Output - Actual Output ie. error;
Ierr = err + Ierr from previous loop; ( i.e. Integral error )
Derr = err - Derr from previous loop; ( i.e. Differential error)
dt = time interval between evaluations/
where initially 'Derr' and 'Ierr' would be zero.

*/

#define Kp 1
#define Ki 1
#define Kd 1
#define Dt 10 //time step (milliseconds)
#define SS_ERR 2    //steady steate error margin (percentage)

unsigned long oldtime=0;
signed int Vin,Vout,setpoint=128;
signed int err_i=0, err_d=0, err_calc=0;

void setup{

}

void loop(){
uint16_t ss_error;
 
 Vin=AnalogRead(0);
 err_calc = setpoint-Vin;
 
 ss_error = (abs(err_calc)*100)/setpoint; //calculated percentage error
 
 if((millis()-oldtime) > Dt && ss_error > SS_ERR){
 millis = oldtime;

 err_i = err_calc+err_i;
 err_d = err_calc-err_d;
 
 Vout = (Kp * err_calc) + (Ki * err_i * Dt) + ((Kd * err_d) /Dt);
 }

}

you can check out wiki to see how to use it to then tune it. PID controller - Wikipedia :wink: