Hi,
I am implementing automated lighting control using Arduino Uno.Reference lux value is set to 350 and I use a LDR to sense the light and calibrated it into lux value in the program.
But I observe flickering in the light output because the output doesn't settle at desired 350 Lux.
Following is the code
#include<math.h>
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 11; // Analog output pin that the LED is attached to
int sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
}
void loop() {
// read the analog in value:
sensorValue = analogRead(analogInPin);
float three=(-.000029333)*pow(sensorValue,3) ;//program calibration
float two=(.0311)*pow(sensorValue,2); //program calibration
float one=(-11.1963)*sensorValue; //program calibration
float lux= three+two+one+1426; //program calibration
if(lux<=0)
{
lux=0;
}
if(lux>=350)
{
lux=350;
}
Serial.println("lux= " );
Serial.println(lux);
// map it to the range of the analog out:
outputValue = map(lux, 350, 0, 0, 204);
// change the analog out value:
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
analogWrite(analogOutPin, outputValue);
// print the results to the serial monitor:
Serial.println("sensor = " );
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
// wait 2 milliseconds before the next loop
// for the analog-to-digital converter to settle
// after the last reading:
delay(2);
}
I have attached the image of output at the terminal with this post.
Can someone help me to solve this issue?
map() doesn't take float arguments. It makes no sense to call it with a float.
I gave up trying to understand your output. Use print() to print the id. Use println() to print the value. Print the stuff in the order it is read/computed.
Hi, it looks as though you are trying to use the map function to control the output brightness of the LED, if the lumens is low then the map output gives a higher level to brighten the LED and vice versa.
Sorry but as you can see it doesn't work.
You should be using a PID type function.
Or do it set by step.
1 In SETUP, Initially set output to LED to 0.
2 In LOOP, Measure the light level, compare it to the reference POT.
3 If within say 10 higher or lower than POT, do not change level
4 If high then adjust output down a bit, say 5.
5 If low then adjust output up a bit, say 5.
6 Let program loop back to step 2
The looping then tracks the output of the LED.
Its simple, mechanical but it is easy to adjust the variables to suit your situation, I hope.
You will have to program limits, like output 0 to 255.
The 10 higher or lower than POT, is what is called dead-band and stops the program chopping around the set-point, if you make the deadband smaller you will have to also lower the adjustment steps down from the 5 in the example.
Can you please post a copy of your circuit, in CAD or picture of hand drawn circuit in jpg, png or pdf format.
And a picture of your project.
Sorry for the bad output format. I have attached a proper one now.
The issue is that output doesn't converge to the reference value.Initially as the brightness is low, the output PWM is increasing which inturn increases the light output.Now the sensor detects this increased brightness and reduces the PWM value which decreases the brightness.
This loop goes on for ever and this causes flickering of LED lamp and also it doesn't settle at the reference brightness value.
Hi Tom,
I executed as per your logic and got the desired output.The only issue is that constrain function doesn't limit the values.
Here is the code:
#include<math.h>
const int analogInPin = A0; // Analog input pin that the sensor is attached to
const int analogOutPin = 11; // Analog output pin that the LED is attached to
int sensorValue = 0; // value read from the sensor
int outputValue = 0;
float lux=0;
int ref=350; //reference lux value
int tolerance=5; / lux tolerance percentage
float mn=((100-tolerance)/100.0)*ref;
float mx=((100+tolerance)/100.0)*ref;
float pwm;
int sampling=10000; //sensor sampling interval
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
}
void loop() {
// if lux reference is less than 20; switch off the lamp
if(ref<20)
{
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
analogWrite(analogOutPin, 0);
}
/*Serial.print("minimum= " );
Serial.println(mn);
Serial.print("maximum= " );
Serial.println(mx); */
// find the corrsponding PWM value for reference:
if(lux<mn || lux>mx)
{
float a=(-0.00012415)*ref*ref;
float b=0.2901*ref;
pwm=a+b+1.0156;
Serial.print("initial pwm");
Serial.println(pwm);
outputValue=pwm*2.55;
Serial.print("initial output");
Serial.println(outputValue);
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
analogWrite(analogOutPin, outputValue);
//convert the sensor input value to lux value
sensorValue = analogRead(analogInPin);
Serial.print("initial sensor = " );
Serial.println(sensorValue);
float three=(-.000029333)*sensorValue*sensorValue*sensorValue ;
float two=(.0311)*pow(sensorValue,2);
float one=(-11.1963)*sensorValue;
lux= three+two+one+1426;
Serial.print("initial lux = ");
constrain(lux, 0, 500);
Serial.println(lux);
for(;lux<mn;)
{
outputValue=outputValue+5;
constrain(outputValue, 0, 255);
Serial.print("output value = " );
Serial.println(outputValue);
analogWrite(analogOutPin, outputValue);
sensorValue = analogRead(analogInPin);
float three=(-.000029333)*sensorValue*sensorValue*sensorValue ;
float two=(.0311)*pow(sensorValue,2);
float one=(-11.1963)*sensorValue;
lux= three+two+one+1426;
constrain(lux, 0, 500);
Serial.print("lux= " );
Serial.println(lux);
}
for(;lux>mx;)
{
outputValue=outputValue-5;
constrain(outputValue, 0, 255);
Serial.print("output value = " );
Serial.println(outputValue);
analogWrite(analogOutPin, outputValue);
sensorValue = analogRead(analogInPin);
float three=(-.000029333)*sensorValue*sensorValue*sensorValue ;
float two=(.0311)*pow(sensorValue,2);
float one=(-11.1963)*sensorValue;
lux= three+two+one+1426;
constrain(lux, 0, 500);
Serial.print("lux= " );
Serial.println(lux);
}
}
/* Serial.print("output value = " );
Serial.println(outputValue);*/
//sample the brighness again after a delay
delay(sampling);
sensorValue = analogRead(analogInPin);
float three=(-.000029333)*sensorValue*sensorValue*sensorValue ;
float two=(.0311)*pow(sensorValue,2);
float one=(-11.1963)*sensorValue;
lux= three+two+one+1426;
constrain(lux, 0, 500);
Serial.print("lux= " );
Serial.println(lux);
}
you can see from the code that I have constrained lux between 0 to 500(this is because i get negative lux value after calibration) and output to 0 to 255( so that PWM output doesn't exceed 255).
Any help on that front will be appreciated.Thank you
If lux is less than 0, return 0, and discard the result.
If lux is greater than 500, return 500, and discard the result.
If lux is between 0 and 500, return the value of lux, and discard the result.
You might as well delete this line for all the good it is doing.
for(;lux<mn;)
That's about the stupidest for loop I've ever seen. It just screams clueless.
Hi,
I have modified the program to receive reference LUX value from user.
Here is the part of the code for receiving the reference value
if (Serial.available() ==3)
{
// read the incoming byte:
Serial.readBytesUntil('\n',buffer1, 3);
ref=atoi(buffer1);
Serial.print("Reference Lux value :");
Serial.println(ref);
}
The problem here is that,If the user enters say "12345" it takes "123" as reference value and executes the program.And next time when user enters say "234" it clubs the remaining "45" entered in the previous input with "2" and takes the reference lux to be "452".This loop goes on.
How can I clear the remaining nos after the input is taken?
I tried the following code.But it doesn't help
if (Serial.available() ==3)
{
// read the incoming byte:
Serial.readBytesUntil('\n',buffer1, 3);
ref=atoi(buffer1);
Serial.print("Reference Lux value :");
Serial.println(ref);
while(Serial.available())
{
Serial.read();
}
}
I would suggest you start you program from scratch and build it up section by section.
I cannot see anything in your program that looks like the process I described.
You need to add structure to your programming.
I am surprised it complied after fixing a missing / in line 9.
Also can you do TOOLS, AUTO FORMAT please in the IDE to offset the for and if functions.
Tom....
Can you please post a copy of your circuit, in CAD or picture of hand drawn circuit in jpg, png or pdf format.
I agree. And to start, forget the lux calculations and try to get the led to return an analogRead() value first.
Then you can add the math for lux . All you have to do is map the lux input to a number from 0-1023, IMO it looks like a lot of unnecessary machinations.
The code which I have put earlier works perfectly for my requirement.
The only issue is constrain function. It doesnt seem to execute what it is supposed to do.Right now I am using IF loop to acheive the same,But as you know it takes more space.And the second issue is about how to clear extra values stored at buffer if more than 3 digits are entered. It will be helpful if someone can clear that.I can't ask the user to type exactly only 3 digit nos for receiving lux values.
Hi Tom,
I will upload the circuit diagram soon. For ur reference,following is the structured code
#include<math.h>
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 11; // Analog output pin that the LED is attached to
int sensorValue = 0; // value read from the pot
int outputValue = 0;
float lux=0;
int ref=350;
int tolerance=5;
float mn=((100-tolerance)/100.0)*ref;
float mx=((100+tolerance)/100.0)*ref;
float pwm;
int sampling=10000;
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
}
void loop() {
if(ref<20)
{
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
analogWrite(analogOutPin, 0);
}
/*Serial.print("minimum= " );
Serial.println(mn);
Serial.print("maximum= " );
Serial.println(mx); */
// read the analog in value:
if(lux<mn || lux>mx)
{
float a=(-0.00012415)*ref*ref;
float b=0.2901*ref;
pwm=a+b+1.0156;
Serial.print("initial pwm");
Serial.println(pwm);
outputValue=pwm*2.55;
Serial.print("initial output");
Serial.println(outputValue);
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
analogWrite(analogOutPin, outputValue);
sensorValue = analogRead(analogInPin);
Serial.print("initial sensor = " );
Serial.println(sensorValue);
float three=(-.000029333)*sensorValue*sensorValue*sensorValue ;
float two=(.0311)*pow(sensorValue,2);
float one=(-11.1963)*sensorValue;
lux= three+two+one+1426;
Serial.print("initial lux = ");
constrain(lux, 0, 500);
Serial.println(lux);
for(;lux<mn;)
{
outputValue=outputValue+5;
constrain(outputValue, 0, 255);
Serial.print("output value = " );
Serial.println(outputValue);
analogWrite(analogOutPin, outputValue);
sensorValue = analogRead(analogInPin);
float three=(-.000029333)*sensorValue*sensorValue*sensorValue ;
float two=(.0311)*pow(sensorValue,2);
float one=(-11.1963)*sensorValue;
lux= three+two+one+1426;
constrain(lux, 0, 500);
Serial.print("lux= " );
Serial.println(lux);
}
for(;lux>mx;)
{
outputValue=outputValue-5;
constrain(outputValue, 0, 255);
Serial.print("output value = " );
Serial.println(outputValue);
analogWrite(analogOutPin, outputValue);
sensorValue = analogRead(analogInPin);
float three=(-.000029333)*sensorValue*sensorValue*sensorValue ;
float two=(.0311)*pow(sensorValue,2);
float one=(-11.1963)*sensorValue;
lux= three+two+one+1426;
constrain(lux, 0, 500);
Serial.print("lux= " );
Serial.println(lux);
}
}
/* Serial.print("output value = " );
Serial.println(outputValue);*/
delay(sampling);
sensorValue = analogRead(analogInPin);
float three=(-.000029333)*sensorValue*sensorValue*sensorValue ;
float two=(.0311)*pow(sensorValue,2);
float one=(-11.1963)*sensorValue;
lux= three+two+one+1426;
constrain(lux, 0, 500);
Serial.print("lux= " );
Serial.println(lux);
}
The problem here is that,If the user enters say "12345" it takes "123" as reference value and executes the program.And next time when user enters say "234" it clubs the remaining "45" entered in the previous input with "2" and takes the reference lux to be "452".This loop goes on.
Can u help me solve this issue? I tried limiting the buffer size to 4 (3 data bytes and one for '\n').But it doesn't help. Here is the code
char buffer1[ 4];
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
Serial.println("enter reference lux value");
}
void loop()
{
if (Serial.available() ==3)
{
// read the incoming byte:
Serial.readBytesUntil('\n',buffer1, 3);
Serial.print("Buffer :");
Serial.println(buffer1);
int ref=atoi(buffer1);
Serial.print("Reference Lux value :");
Serial.println(ref);
}
}
I am trying to implement the same thing wireless.
The Light sensors will communicate to the Light control arduino node through xbee radios (S2). I have put two light sensors to communicate with the control node.
I am a newbie to zigbee communication. I want to learn to configure these xbee in API mode.I am using X-CTU version 6.1.1 to configure.Any help would be appreciated.
I have configured them as follows
Radio 1.
XB24-ZB Ver:21A7
ZIGBEE COORDINATOR API
Pan ID: 10
SH:13A200
SL:4086DE9E
DH:13A200
DL:40B3EE21
Radio 2.
XB24-ZB Ver:29A7
ZIGBEE ROUTER API
PAN ID :10
SH:13A200
SL:40B3EE21
DH:13A200
DL:4086DE9E
I checked for the network topology and found both nodes are connected.Pls find the attached image for the topology.
Now how to test communication between them?. I tried to communicate as in AT mode by typing in one console and receiving the same in another radios console. But API mode is asking for frames. I have attached the image of the screen. Can someone help on how to proceed from here?