I'm trying to design a dual axis solar tracker using an Arduino Uno-R3.
Basically it just takes the input from the LDR and outputs the PWM signal to the two 9g servo motors for each axis. The question that I'm wondering is that why is the PWM output inconsistent on the servo? I'm powering the Arduino with a USB port from my laptop. enter image description here
Here is the code :
#include <Servo.h>
#include <avr/sleep.h> // contains methods that controls sleep modes
//analog input range from 0 to 1023 to correspond to voltage between 0V to 5V.
Servo horizontal; // horizontal servo
Servo vertical; // vertical servo
int servoHori = 90; // horizontal servo initial position
int servoHoriLimitHigh = 180; // limit rotation angle for horizontal servo
int servoHoriLimitLow = 0;
int servoVerti = 0; // vertical servo initial position
int servoVertiLimitHigh = 90; // limit rotation angle for vertical servo
int servoVertiLimitLow = 0;
// LDR = analogpin;
int ldrlt = 0; //LDR left top
int ldrrt = 1; //LDR right top
int ldrld = 2; //LDR left down
int ldrrd = 3; //LDR right down
int triggerPin = 2; // digital pin 2 for interrupt
void wakeUpNow() //interrupt service routine
{
delay(100);
}
void setup() //
{
Serial.begin(9600); //set the Arduino to transmit at 9600 bits per second (default baud rate).
horizontal.attach(9); //horizontal servo to pin 9
vertical.attach(10); // vertical servo to pin 10
horizontal.write(90);
vertical.write(0);
delay(3000);
}
void loop()
{
int lt = analogRead(ldrlt); // top left
int rt = analogRead(ldrrt); // top right
int ld = analogRead(ldrld); // down left
int rd = analogRead(ldrrd); // down right
// To scale the numbers between 0.0 and 5.0, divide 5.0 by 1023.0 and multiply that by sensorValue
float voltage = lt * (5.0 / 1023.0);
float voltage1= rt * (5.0 / 1023.0);
float voltage2= ld * (5.0 / 1023.0);
float voltage3= rd * (5.0 / 1023.0);
// pulseIn(pin, value) pin, type of pulse high or low
int pin9 = 9;
int pin10 = 10;
unsigned long ServoHpwm;
unsigned long ServoVpwm;
ServoHpwm = pulseIn(pin9, HIGH);
ServoVpwm = pulseIn(pin10, HIGH);
int deltime = 10;
int tol = 50;
int avt = (lt + rt) / 2; // average value top
int avd = (ld + rd) / 2; // average value down
int avl = (lt + ld) / 2; // average value left
int avr = (rt + rd) / 2; // average value right
int Diffvert = avt - avd; // check the difference of up and down
int Diffhoriz = avl - avr;// check the difference of left and right
int ldrtot = avt + avd + avl + avr; //total value of ldr
Serial.print(voltage);
Serial.print(" ");
Serial.print(voltage1);
Serial.print(" ");
Serial.print(voltage2);
Serial.print(" ");
Serial.print(voltage3);
Serial.print(" ");
Serial.print(deltime);
Serial.print(" ");
Serial.print(tol);
Serial.print(" ");
Serial.print(" ServoHpwm ");
Serial.print(ServoHpwm);
Serial.print(" ServoVpwm ");
Serial.print(ServoVpwm);
Serial.println(" ");
if (-1*tol > Diffvert || Diffvert > tol) // check if the difference is in the tolerance else change vertical angle
{
if (avt > avd)
{
servoVerti = ++servoVerti; // if avt>avd vertical servo angle increase
if (servoVerti > servoVertiLimitHigh) // make sure vertical servo wont overshoot high limit
{
servoVerti = servoVertiLimitHigh;
}
}
else if (avt < avd)
{
servoVerti= --servoVerti; // if avt<avd vertical servo angle decrease
if (servoVerti < servoVertiLimitLow) // make sure vertical servo wont overshoot low limit
{
servoVerti = servoVertiLimitLow;
}
}
vertical.write(servoVerti); //Writes binary data to the serial port
}
if (-1*tol > Diffhoriz || Diffhoriz > tol) // check if the difference is in the tolerance else change horizontal angle
{
if (avl > avr)
{
servoHori = --servoHori; // if avl>avr, horizontal servo angle decrease
if (servoHori < servoHoriLimitLow)
{
servoHori = servoHoriLimitLow; // make sure horizontal servo wont overshoot low limit (0)
}
}
else if (avl < avr)
{
servoHori = ++servoHori; // if avl<avr horizontal servo angle increase
if (servoHori > servoHoriLimitHigh) // make sure horizontal servo wont overshooot high limit (180)
{
servoHori = servoHoriLimitHigh;
}
}
else if (avl = avr)
{
// nothing
}
horizontal.write(servoHori);
}
if ( ldrtot < 800)
{
servoHori=90;
servoVerti=0;
if(ldrtot < 800)
{
sleep_enable(); // enables the sleep bit in the mcucr register
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
attachInterrupt (0,wakeUpNow,RISING);
sleep_mode(); // here the device is actually put to sleep
sleep_disable();
detachInterrupt(0);
}
}
delay(deltime);
}
-
1\$\begingroup\$ In what way are the PWM signals inconsistant? \$\endgroup\$JRE– JRE2020年05月10日 21:25:35 +00:00Commented May 10, 2020 at 21:25
-
\$\begingroup\$ @JRE For instance if you look at the serial port output, the voltages from the LDR are constant but the PWM outputs are fluctuating \$\endgroup\$Wkayy10– Wkayy102020年05月10日 21:36:49 +00:00Commented May 10, 2020 at 21:36
1 Answer 1
Your problem lies in trying to read the PWM signal using pulseIn on the same channel you are doing servo.write.
You are changing the PWM width, then at some point you ask for a pulseIn. That command waits for a state transition on the specified pin.
Since the PWM signal and the start of the pulseIn wait period aren't synchronized, you read various pulse periods.
Don't bother with pulseIn. You are setting the pulse width using servo.write. Just log the value (servoHori and servoVerti) that you calculate and be done with it. Or are you concerned that the Arduino library won't actually set the pulse width (or angle) that you specified?
-
\$\begingroup\$ Thanks for replying, i understood what i did wrong. \$\endgroup\$Wkayy10– Wkayy102020年05月14日 11:59:06 +00:00Commented May 14, 2020 at 11:59