Sketch Overview:
The sketch compiles and is working as intended.
The servo rotates forward from angle/degree "0" to "180". If the DC current monitor detects any value from the servo above a certain threshold along the way, the servo immediately stops rotating forward and goes backward to its original starting position (and then loops indefinitely)
Issue:
Sometimes the current monitor will detect a single current "spike" coming from the servo motor while it rotates. This "spike" then trips the flag and sends the servo rotating backwards.
Is there any way that I can tell the current monitor to ignore a single current spike and only trip the flag when x3 consecutive spikes are detected?
#include <Wire.h> //Used for the current monitor
#include <Servo.h> //Servo library
#include <Adafruit_INA219.h> //Current monitor library
Adafruit_INA219 ina219_3; //Instance for the current monitor
Servo Servo3; //Instance for the servo motor
int Servo3_Position = 0; //Variable to store Servo3's degree/angle
//---------------
void setup()
{
Serial.begin(115200); //Baud rate
ina219_3.begin(); //Start the current monitor
uint32_t currentFrequency; //Used for the current monitor. Unsure what this actually does, but the current monitor won't work properly without it.
Servo3.attach(9); //Attach Servo3 on PWM pin 9
Servo3.write(0); //Send Servo3 to the starting angle/degree ("0")
delay(1500); //Let Servo3 run for 1.5 seconds to get to angle/degree ("0") if it's not alreay there
}
//---------------
void loop()
{
for (Servo3_Position = 0; Servo3_Position <= 180; Servo3_Position += 1) //Servo3 goes from 0 angle/degree to 180 angle/degree in increments of +1 angle/degree at a time
{
Servo3.write(Servo3_Position); //Tells Servo3 to go to position in variable 'Servo3_Position'
float current_mA = 0; //This is for the current monitor
current_mA = ina219_3.getCurrent_mA(); //This is for the current monitor
Serial.print("Forward: "); //Serial print which direction Servo3 is rotating
Serial.print(current_mA); //Serial print the variable "current_mA"
Serial.println(" mA"); //Serial print "mA" after printing the variable current_mA
Serial.print("Angle: "); //Serial print the angle of Servo3
Serial.println(Servo3_Position); //Serial print the variable "Servo3 Position"
Serial.println(""); //Serial print a blank line for spacing
delay(15); //This delay controls Servo3's rotational speed from 1 angle to the next. Example: Going from angle 5 to angle 6 has a delay of 15 ms in between
if ((current_mA) >= 175.00) //If the current monitor detects a value greater than or equal to 175.00
{
Servo3.detach(); //Disconnect Servo3 from PWM pin 9
Serial.println("Flag - FORWARD");
Serial.println();
Servo3.attach(9); //Reconnect Servo3 to PWM pin 9
Servo3.write(0); //Send Servo3 back to the starting angle/degree ("0")
delay(1500); //Let Servo3 run for 1.5 seconds to get back to angle/degree ("0")
break; //Exit the "if" loop
}
}
Serial.print("////////////////////////////////////"); //Serial print a dividing line for easy viewing
Serial.println();
Serial.println();
delay (1000); //Once Servo3 has reached angle/degree 180, wait for 1 second
Servo3.write(0); //Send Servo3 back to the starting angle/degree ("0") without monitoring current
delay(1500); //Let Servo3 run for 1.5 seconds to get back to angle/degree ("0")
}
Do You have access to an oscilloscope capable of registering that disturbing pulse, checking the length of it?
One way could be to make a second current reading when that pulse occur. If the second reading also finds a pulse, then it's a trigger, else, ignore.
Okey.
Try a 1 mS or a few, delay and a second reading to verify.
Make sure that that You don't miss the real situation, when the return move must be done.
@Railroader It's working! Thank you sir!! That's a pretty clever trick you suggested
Edited sketch with the suggestions from @Railroader
#include <Wire.h> //Used for the current monitor
#include <Servo.h> //Servo library
#include <Adafruit_INA219.h> //Current monitor library
Adafruit_INA219 ina219_3; //Instance for the current monitor
Servo Servo3; //Instance for the servo motor
int Servo3_Position = 0; //Variable to store Servo3's degree/angle
//---------------
void setup()
{
Serial.begin(115200); //Baud rate
ina219_3.begin(); //Start the current monitor
uint32_t currentFrequency; //Used for the current monitor. Unsure what this actually does, but the current monitor won't work properly without it.
Servo3.attach(9); //Attach Servo3 on PWM pin 9
Servo3.write(0); //Send Servo3 to the starting angle/degree ("0")
delay(1500); //Let Servo3 run for 1.5 seconds to get to angle/degree ("0") if it's not alreay there
}
//---------------
void loop()
{
for (Servo3_Position = 0; Servo3_Position <= 180; Servo3_Position += 1) //Servo3 goes from 0 angle/degree to 180 angle/degree in increments of +1 angle/degree at a time
{
Servo3.write(Servo3_Position); //Tells Servo3 to go to position in variable 'Servo3_Position'
float current_mA = 0; //This is for the current monitor
current_mA = ina219_3.getCurrent_mA(); //This is for the current monitor
Serial.print("Forward: "); //Serial print which direction Servo3 is rotating
Serial.print(current_mA); //Serial print the variable "current_mA"
Serial.println(" mA"); //Serial print "mA" after printing the variable current_mA
Serial.print("Angle: "); //Serial print the angle of Servo3
Serial.println(Servo3_Position); //Serial print the variable "Servo3 Position"
Serial.println(""); //Serial print a blank line for spacing
delay(15); //This delay controls Servo3's rotational speed from 1 angle to the next. Example: Going from angle 5 to angle 6 has a delay of 15 ms in between
if ((current_mA) >= 150.00) //If the current monitor detects a value greater than or equal to 175.00
{
delay(1);
Serial.println("Flag #1 - FORWARD");
float current_mA = 0; //This is for the current monitor
current_mA = ina219_3.getCurrent_mA(); //This is for the current monitor
Serial.print("Forward: "); //Serial print which direction Servo3 is rotating
Serial.print(current_mA); //Serial print the variable "current_mA"
Serial.println(" mA"); //Serial print "mA" after printing the variable current_mA
Serial.print("Angle: "); //Serial print the angle of Servo3
Serial.println(Servo3_Position); //Serial print the variable "Servo3 Position"
Serial.println(""); //Serial print a blank line for spacing
if ((current_mA) >= 150.00) //If the current monitor detects a value greater than or equal to 175.00
{
delay(1);
Serial.println("Flag #2 - FORWARD");
float current_mA = 0; //This is for the current monitor
current_mA = ina219_3.getCurrent_mA(); //This is for the current monitor
Serial.print("Forward: "); //Serial print which direction Servo3 is rotating
Serial.print(current_mA); //Serial print the variable "current_mA"
Serial.println(" mA"); //Serial print "mA" after printing the variable current_mA
Serial.print("Angle: "); //Serial print the angle of Servo3
Serial.println(Servo3_Position); //Serial print the variable "Servo3 Position"
Serial.println(""); //Serial print a blank line for spacing
if ((current_mA) >= 150.00) //If the current monitor detects a value greater than or equal to 175.00
{
Serial.println("Flag #3 - FORWARD");
float current_mA = 0; //This is for the current monitor
current_mA = ina219_3.getCurrent_mA(); //This is for the current monitor
Serial.print("Forward: "); //Serial print which direction Servo3 is rotating
Serial.print(current_mA); //Serial print the variable "current_mA"
Serial.println(" mA"); //Serial print "mA" after printing the variable current_mA
Serial.print("Angle: "); //Serial print the angle of Servo3
Serial.println(Servo3_Position); //Serial print the variable "Servo3 Position"
Serial.println(""); //Serial print a blank line for spacing
if ((current_mA) >= 150.00) //If the current monitor detects a value greater than or equal to 175.00
{
Servo3.detach(); //Disconnect Servo3 from PWM pin 9
Serial.println("Flag - FORWARD");
Serial.println();
Servo3.attach(9); //Reconnect Servo3 to PWM pin 9
Servo3.write(0); //Send Servo3 back to the starting angle/degree ("0")
delay(1500); //Let Servo3 run for 1.5 seconds to get back to angle/degree ("0")
break; //Exit the "if" loop
}
}
}
}
}
Serial.print("////////////////////////////////////"); //Serial print a dividing line for easy viewing
Serial.println();
Serial.println();
delay (1000); //Once Servo3 has reached angle/degree 180, wait for 1 second
Servo3.write(0); //Send Servo3 back to the starting angle/degree ("0") without monitoring current
delay(1500); //Let Servo3 run for 1.5 seconds to get back to angle/degree ("0")
}
Store the number of consecutive spikes and the timestamp (millis) of the last spike. Run a function in the loop that looks at the current millis and the last spike millis; if it's longer than X milliseconds, clear the number of spikes and the stored timestamp. If the number of spikes is 3, trigger your servo to reverse direction. Fairly straightforward.
@Railroader's solution will also work of course, albeit with slightly different behavior.
It's only showing x1 flag when a normal current spike occurs, then it continues reading as shown in the first screenshot. However, if I manually stall the servo, it will flag x3 and then trip the real flag to reset the servo back to it's home position - (screenshot 2)
Fine!
I suggest that You can comment out "Flag3" in order to speed up the response time when the hard stop is reached.
Doing some more thinking about the pulse, how, from where it comes and get the signal more reliable is not bad.
@Railroader I tried removing "Flag3" like you suggested, but it causes too many resets.
Unfortunately, sometimes when the servo resets normally back to 0 and begins rotating, there are multiple power spikes which trips the flags and resets the servo back to 0.
I was able to get rid of the last issue I was having where the servo would flag x3 and rest upon starting by adding "&& Servo3_Position >= 15" to the 1st flag condition!
This allows the servo to keep rotating without flagging through the first 15 angles/degrees. After that, it will begin monitoring the servos current draw.
#include <Wire.h> //Used for the current monitor
#include <Servo.h> //Servo library
#include <Adafruit_INA219.h> //Current monitor library
Adafruit_INA219 ina219_3; //Instance for the current monitor
Servo Servo3; //Instance for the servo motor
int Servo3_Position = 0; //Variable to store Servo3's degree/angle
//---------------
void setup()
{
Serial.begin(115200); //Baud rate
ina219_3.begin(); //Start the current monitor
uint32_t currentFrequency; //Used for the current monitor. Unsure what this actually does, but the current monitor won't work properly without it.
Servo3.attach(9); //Attach Servo3 on PWM pin 9
Servo3.write(0); //Send Servo3 to the starting angle/degree ("0")
delay(1500); //Let Servo3 run for 1.5 seconds to get to angle/degree ("0") if it's not alreay there
}
//---------------
void loop()
{
for (Servo3_Position = 0; Servo3_Position <= 180; Servo3_Position += 1) //Servo3 goes from 0 angle/degree to 180 angle/degree in increments of +1 angle/degree at a time
{
Servo3.write(Servo3_Position); //Tells Servo3 to go to position in variable 'Servo3_Position'
float current_mA = 0; //This is for the current monitor
current_mA = ina219_3.getCurrent_mA(); //This is for the current monitor
Serial.print("Forward: "); //Serial print which direction Servo3 is rotating
Serial.print(current_mA); //Serial print the variable "current_mA"
Serial.println(" mA"); //Serial print "mA" after printing the variable current_mA
Serial.print("Angle: "); //Serial print the angle of Servo3
Serial.println(Servo3_Position); //Serial print the variable "Servo3 Position"
Serial.println(""); //Serial print a blank line for spacing
delay(15); //This delay controls Servo3's rotational speed from 1 angle to the next. Example: Going from angle 5 to angle 6 has a delay of 15 ms in between
if ((current_mA) >= 120.00 && Servo3_Position > 15) //If the current monitor detects a value greater than or equal to 120.00 and has an "Angle" of greater than 15
{
delay(1);
Serial.println("*****FLAG #1*****");
Serial.println();
float current_mA = 0; //This is for the current monitor
current_mA = ina219_3.getCurrent_mA(); //This is for the current monitor
Serial.print("Forward: "); //Serial print which direction Servo3 is rotating
Serial.print(current_mA); //Serial print the variable "current_mA"
Serial.println(" mA"); //Serial print "mA" after printing the variable current_mA
Serial.print("Angle: "); //Serial print the angle of Servo3
Serial.println(Servo3_Position); //Serial print the variable "Servo3 Position"
Serial.println(""); //Serial print a blank line for spacing
if ((current_mA) >= 120.00) //If the current monitor detects a value greater than or equal to 120.00 and the angle is greater or equal to 10
{
delay(1);
Serial.println("*****FLAG #2*****");
Serial.println();
float current_mA = 0; //This is for the current monitor
current_mA = ina219_3.getCurrent_mA(); //This is for the current monitor
Serial.print("Forward: "); //Serial print which direction Servo3 is rotating
Serial.print(current_mA); //Serial print the variable "current_mA"
Serial.println(" mA"); //Serial print "mA" after printing the variable current_mA
Serial.print("Angle: "); //Serial print the angle of Servo3
Serial.println(Servo3_Position); //Serial print the variable "Servo3 Position"
Serial.println(""); //Serial print a blank line for spacing
if ((current_mA) >= 120.00) //If the current monitor detects a value greater than or equal to 120.00
{
Serial.println("*****FLAG #3*****");
Serial.println();
float current_mA = 0; //This is for the current monitor
current_mA = ina219_3.getCurrent_mA(); //This is for the current monitor
Serial.print("Forward: "); //Serial print which direction Servo3 is rotating
Serial.print(current_mA); //Serial print the variable "current_mA"
Serial.println(" mA"); //Serial print "mA" after printing the variable current_mA
Serial.print("Angle: "); //Serial print the angle of Servo3
Serial.println(Servo3_Position); //Serial print the variable "Servo3 Position"
Serial.println(""); //Serial print a blank line for spacing
if ((current_mA) >= 120.00) //If the current monitor detects a value greater than or equal to 120.00
{
Servo3.detach(); //Disconnect Servo3 from PWM pin 9
Serial.println("*****RESET FLAG*****");
Serial.println();
Servo3.attach(9); //Reconnect Servo3 to PWM pin 9
Servo3.write(0); //Send Servo3 back to the starting angle/degree ("0")
delay(1500); //Let Servo3 run for 1.5 seconds to get back to angle/degree ("0")
break; //Exit the "if" loop
}
}
}
}
}
Serial.print("////////////////////////////////////"); //Serial print a dividing line for easy viewing
Serial.println();
Serial.println();
delay (1000); //Once Servo3 has reached angle/degree 180, wait for 1 second
Servo3.write(0); //Send Servo3 back to the starting angle/degree ("0") without monitoring current
delay(1500); //Let Servo3 run for 1.5 seconds to get back to angle/degree ("0")
}