Hi, I have constructed a solar tracker with a H-bridge with mosfets and bjts to control a linear actuator. For bench testing I have set a day light threshold of 600 and night light threshold of 500, also the tracking time is set at 5 second for west and east. But I have set the run time for night east return at 10 seconds. The east and west tracking is working fine, but there is a conflict with east return which is a reverse command as is the east tracking command. When under night light threshold the actuator keeps stopping after 2-3 second and does not run for the ten seconds as I have put in the millis() function. I am new to coding, so I was wondering if anyone has any suggestions or ideas that could help me resolve this coding conflict? I have included my sketch.
int sense1Pin = A0; //west leds
int sense2Pin = A1; //east leds
int forward = 9; // use pin 9 for forward
int reverse = 10; // use pin 10 for reverse
int tolerance = 20;
unsigned long previous_F_Millis = 0; // stores the value of millis() in each iteration of loop()
unsigned long previous_R_Millis = 0;
unsigned long previous_ER_Millis = 0; // will store last time motor was updated
const long interval_one = 5000; // constant won't change, interval motor run (milliseconds)
const long interval_two = 10000;
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
analogReference(DEFAULT);
lcd.begin(16, 2);
Serial.begin(9600);
pinMode(forward, OUTPUT);
pinMode(reverse, OUTPUT);
delay(1000);
digitalWrite(forward, HIGH);
delay(1000);
digitalWrite(forward, LOW);
delay(1000);
digitalWrite(reverse, HIGH);
delay(1000);
digitalWrite(reverse, LOW);
delay(3000);
}
void loop() {
int val1 = analogRead(sense1Pin);
int val2 = analogRead(sense2Pin);
unsigned long currentMillis = millis();
if (val1 + val2 > 600)
if (currentMillis - previous_F_Millis >= interval_one) {
previous_F_Millis = currentMillis;
if ((val1 + val2 > 600) && (val1 > val2 + tolerance))
digitalWrite(forward, HIGH);
else digitalWrite(forward, LOW);
}
if ( val1 + val2 > 600);
if (currentMillis - previous_R_Millis >= interval_one) {
previous_R_Millis = currentMillis;
if ((val1 + val2 > 600) && (val2 > val1 + tolerance))
digitalWrite(reverse, HIGH);
else digitalWrite(reverse, LOW);
}
else (val1 + val2 < 500 );
if (currentMillis - previous_ER_Millis >= interval_two) {
previous_ER_Millis = currentMillis;
if (val1 + val2 < 500 )
digitalWrite(reverse, HIGH);
else digitalWrite(reverse, LOW);
}
lcd.setCursor(1, 0); // set cursor to column 0, row 0 (first row)
lcd.print("West=");
lcd.print(val1);
lcd.setCursor(1, 1);
lcd.print("East=");
lcd.print(val2);
Serial.println(analogRead(sense1Pin));
delay(1000);
Serial.println(analogRead(sense2Pin));
delay(1000);
}
// end of code.
Thank you for your reply MarkT. You are right those lines of code were superfluous and I have removed them, making my sketch much cleaner. But that did not resolve the conflict, the reverse with the night time threshold still only runs for 2-3 seconds, if you have any more suggestions or ideas on that particular topic I would love to hear them. I have included the cleaned up sketch.
int sense1Pin = A0; //west leds
int sense2Pin = A1; //east leds
int forward = 9; // use pin 9 for forward
int reverse = 10; // use pin 10 for reverse
int tolerance = 20;
unsigned long previous_F_Millis = 0; // stores the value of millis() in each iteration of loop()
unsigned long previous_R_Millis = 0;
unsigned long previous_ER_Millis = 0; // will store last time motor was updated
const long interval_one = 5000; // constant won't change, interval motor run (milliseconds)
const long interval_two = 10000;
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
analogReference(DEFAULT);
lcd.begin(16, 2);
Serial.begin(9600);
pinMode(forward, OUTPUT);
pinMode(reverse, OUTPUT);
delay(1000);
digitalWrite(forward, HIGH);
delay(1000);
digitalWrite(forward, LOW);
delay(1000);
digitalWrite(reverse, HIGH);
delay(1000);
digitalWrite(reverse, LOW);
delay(3000);
}
void loop() {
int val1 = analogRead(sense1Pin);
int val2 = analogRead(sense2Pin);
unsigned long currentMillis = millis();
if (currentMillis - previous_F_Millis >= interval_one) {
previous_F_Millis = currentMillis;
if ((val1 + val2 > 600) && (val1 > val2 + tolerance))
digitalWrite(forward, HIGH);
else digitalWrite(forward, LOW);
}
if (currentMillis - previous_R_Millis >= interval_one) {
previous_R_Millis = currentMillis;
if ((val1 + val2 > 600) && (val2 > val1 + tolerance))
digitalWrite(reverse, HIGH);
else digitalWrite(reverse, LOW);
}
if (currentMillis - previous_ER_Millis >= interval_two) {
previous_ER_Millis = currentMillis;
if (val1 + val2 < 500 )
digitalWrite(reverse, HIGH);
else digitalWrite(reverse, LOW);
}
lcd.setCursor(1, 0); // set cursor to column 0, row 0 (first row)
lcd.print("West=");
lcd.print(val1);
lcd.setCursor(1, 1);
lcd.print("East=");
lcd.print(val2);
Serial.println(analogRead(sense1Pin));
delay(1000);
Serial.println(analogRead(sense2Pin));
delay(1000);
}
// end of code.
Thank you for your response, if the problem was mechanical, electrical or related to the power supply it would manifest it’s self in all aspects of operation. The problems lies in the coding and that’s where I am looking for some assistance.
I thank you for your opinion, I assure you that I have rigorously tested all the mechanical, electrical and power sources for possible faults before I concluded that it is a coding issue. If you are able to help me in that area I would be most appreciative.
jremington, I gave a description of the hardware in my original post. You are being as useful as the proverbial piranha in a hot tub. I have politely asked for some help trouble shooting my coding, if you do not wish to aid in that effort, I suggest you stop leaving unhelpful comments on this post.
Alright, jremington, you obviously have a lot of time on your hands. The DC linear actuator is a 18" 12 volt 5 amp model using a acme screw. The power supply is a 12 volt 9 amp hour sla battery connected to a buck voltage regulator. That power goes to the arduino through another voltage regulator that provides 9 volts and 500 m amps. The h - bridge has two p- channel mosfets and two n- channel mosfets controlled by 2 NPN bi polar transistors. I hope all this hardware information helps you in finding what is wrong with the timing issue I have in the coding.
I hope all this hardware information helps you in finding what is wrong with the timing issue I have in the coding.
Hardware should be easy to check. Take the wire attached to the arduino forward pin and connect it to the arduino 5v pin and see if the motor runs in forward direction. Take the the wire attached to the arduino reverse pin and connect it to the arduino 5v pin and see if the motor runs in reverse. If the motor does not respond as expected, then you probably have hardware, wiring, or power issues.
You have found the use of serial monitor, you are sending 2 read values at the end of every iteration.
Serial monitor is a very powerful debug tool, you can find out stuff about every step in your sketch.
Use it and use it wisely.
Send a notice whenever you’re at the start of another iteration, or evenavery time you go through setup.
That will let you know how many resets have occurred.
Send a line when you start a motor movement, and another one when you’re done with that.
After you’re done debugging, you can get rid of any serial communication you do not need any longer.
I think your problem is that there is nothing that stops the “short” timers are still running even during your “long” reverse.
Your basic logic looks like:
if (currentMillis - previous_F_Millis >= interval_one) {
// maybe go forward
}
if (currentMillis - previous_R_Millis >= interval_one) {
// maybe short reverse
}
if (currentMillis - previous_ER_Millis >= interval_two) {
// maybe long reverse
}
If the last if clause decides to turn on the motor reverse (to be turned off in 10s), the OTHER if clauses are going to continue to test their stuff every 5 seconds, and one of them is likely (?) to stop the motor before the 10s is up. I’m not sure why this would happen after 2 or 3 seconds rather than 5-ish, but the timers aren’t tightly synced, so some drift if possible.
Hi westfw,
Thanks for your reply. You are absolutely correct in diagnosing that as the problem. After some tests I confirmed that the east tracking reverse code block is turning the high command to low and interfering with the east return ten second time interval. I am going to see if I can isolate the two code blocks to stop that from happening. In the mean time if you have any suggestions or ideas on how to accomplish that I would appreciate it, as my coding abilities are very limited. Thanks again.
One way might be to set the previous_xxx_millis of the other timers into the future in the long timer code,
Pxmillis = millis() + interval two;
Or something. Be sure to add comments if you do this, because it's obscure as hell, and you won't remember why you did it two months from now.
Hi Robin2,
I have not had time to figure out and implement westfw’s millis() idea yet. But I have isolated the problem. Under east return light conditions the actuator goes in reverse but the east tracking code block turns it to low after a few seconds. To combat this I created two while loops in my updated sketch. The effect of the while loop is that while the night light level is below the threshold, east return stays in reverse indefinitely unless the threshold goes above 500, but the coding still does not let it run for the ten seconds that it is suppose to. An improvement but still not right. I have included the updated sketch.
int sense1Pin = A0; //west leds
int sense2Pin = A1; //east leds
int forward = 9; // use pin 9 for forward
int reverse = 10; // use pin 10 for reverse
int tolerance = 20;
unsigned long previous_F_Millis = 0; // stores the value of millis() in each iteration of loop()
unsigned long previous_R_Millis = 0;
unsigned long previous_ER_Millis = 0; // will store last time motor was updated
const long interval_one = 5000; // constant won't change, interval motor run (milliseconds)
const long interval_two = 10000;
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
analogReference(DEFAULT);
lcd.begin(16, 2);
Serial.begin(9600);
pinMode(forward, OUTPUT);
pinMode(reverse, OUTPUT);
delay(1000);
digitalWrite(forward, HIGH);
delay(1000);
digitalWrite(forward, LOW);
delay(1000);
digitalWrite(reverse, HIGH);
delay(1000);
digitalWrite(reverse, LOW);
delay(3000);
}
void loop() {
int val1 = analogRead(sense1Pin);
int val2 = analogRead(sense2Pin);
unsigned long currentMillis = millis();
if (currentMillis - previous_F_Millis >= interval_one) { // west tracking code block
previous_F_Millis = currentMillis;
if ((val1 + val2 > 600) && (val1 > val2 + tolerance))
digitalWrite(forward, HIGH);
else digitalWrite(forward, LOW);
}
{
while (val1 + val2 > 600) {
if (currentMillis - previous_R_Millis >= interval_one) { // east tracking code block
previous_R_Millis = currentMillis;
if ((val1 + val2 > 600) && (val2 > val1 + tolerance))
digitalWrite(reverse, HIGH);
else digitalWrite(reverse, LOW);
}
break;
}
}
{
while (val1 + val2 < 500) {
if (currentMillis - previous_ER_Millis >= interval_two) { // east return code block
previous_ER_Millis = currentMillis;
if (val1 + val2 < 500)
digitalWrite(reverse, HIGH);
else digitalWrite(reverse, LOW);
}
break;
}
}
lcd.setCursor(1, 0); // set cursor to column 0, row 0 (first row)
lcd.print("West=");
lcd.print(val1);
lcd.setCursor(1, 1);
lcd.print("East=");
lcd.print(val2);
Serial.println(analogRead(sense1Pin));
delay(1000);
Serial.println(analogRead(sense2Pin));
delay(1000);
}
// end of code.