Despite finding a solution to solve the problem of knowing when the speed controllers are on or off and have abandoned the ACS712 Low Current Sensor Breakout for this purpose the sensor continues to be useful to monitor the battery status.
|
Figure 1 |
After some research and some help that I have got from this
forum I could do a procedure to test the current sensor. First I have created the circuit shown in figure 1 above, which consists of two parts. One part that includes the Arduino board, the current sensor and a digital voltmeter (I used a multimeter). The other part includes the 9V battery, a resistance, an on/off toggle switch and a micro motor. The idea is to measure the current that flows from the 9V battery to the micro motor.
Before using the current sensor we must calibrate it. Looking at the sensor
specifications I have noticed that the output from the sensor IC is Vcc/2 (~2.5 V, in this case) if there is no current. This is because the sensor IC has a bidirectional output. If the current is "forward", its output is between Vcc/2 and Vcc (~2.5 V and ~5 V, in this case); if the current is "backward", its output is between Gnd and Vcc/2 (~0 V and ~2.5 V, in this case). So let's try to set the board's output to 2.5 V with no input current. According to the note on the
schematic, the two trimpots need to be turned in different directions to increase the values they control. The current sensor uses a
hall-effect sensor internally. Therefore, it should be used a diddle stick (a small non-metallic, non-conductive screwdriver like tool for making fine adjustments) to adjust the trimpot (I used a toothpick and cut it with a x-ato). With a diddle stick, we rotate the "Vref" trimpot until we get the value of ~2.5 V. If we verify that there are great fluctuations in readings, rotates the
"Gain" trimpot until you get readings closer to each other. When we have a more or less stable value, then turns on the motor and immediately we can see an increase in the value of the voltage read by the voltmeter. Remind that the current sensor outputs an analog voltage that varies linearly with sensed current. To read the value of the current sensor in analog pin "0" from the arduino board, I have done a sketch that can be seen below. The values read from the analog pin "0” ranging from 0 to 1023.
/*
Reads values from a ACS712 low current sensor connected to
the analog input pin 0 on Arduino board and print them to
the serial monitor.
*/
void setup() {
Serial.begin(9600); // sets the serial port to 9600
}
void loop() {
int value = analogRead(0); // read analog input pin 0
Serial.println(value, DEC); // prints the value read
delay(1000); // wait 1s for next reading
}
To see the variation of values read from the analog pin "0” in real time I have created a graph using a pair of perl scripts. The first script is a flexible, command-line-oriented frontend to the program “
Gnuplot”. It creates plots from data coming in on STDIN or given in a filename passed on the command line and can be found on this
site. The second script - which can be seen below - allows us to read from the serial port the stream of values received in analog pin "0" of the Arduino board and sends them to the STDIN.
#!/usr/bin/perl -w
use strict;
use Device::SerialPort;
my $port = "/dev/ttyUSB0";
my $ob = Device::SerialPort->new($port);
$ob->databits(8);
$ob->baudrate(9600);
$ob->parity("none");
$ob->stopbits(1);
select STDOUT;
$| = 1;
my $n = 0;
my $buffer = "";
while(1) {
my $byte = $ob->read(1);
if($byte =~ /^\d/) {
$buffer .= $byte;
} elsif($byte =~ /^\n/) {
if($buffer =~ /^\d+/) {
print STDOUT "$buffer\n";
$n++;
sleep(1);
}
$buffer = "";
}
}
undef $ob;
The connection between the two scripts is done with a pipeline (pipe character "|"). The command to start the plot is shown below.
$ ./ReadSerialPort.pl | ./feedGnuplot.pl --stream --lines --points \
--legend "Readings" --title "ACS712 Low Current Sensor Test" \
--ymin 450 --ymax 600 --xlen 100 --xlabel "Time (s)" --ylabel "Value"
In figure 2 we can see the plot in real time and can be observed that there is a sudden increase of the values readed from the sensor, which corresponds to the moment when the motor is turned on. Later, we can observe a decline of values, which correspond to the moment when the motor is turned off.
|
Figure 2 |
As can be seen in the graph of the figure 2, the readings still have a fluctuation although of having reduced the gain as much as possible. The graph displays the raw value from the analog to digital converter (ADC) in the Arduino. After reading some material on the Arduino forum about
smoothing out the values, measuring voltage and converting the raw ADC value to something more useful, I decided to reduce the fluctuation of the readings using the average of 10 readings taken at an interval of 10 ms and then send the result to the Serial port. The new sketch can be seen below.
/*
Computes the average of 10 readings at intervals of 10 ms
from a ACS712 low current sensor connected to the analog
input pin 0 on Arduino board and print them to the serial
monitor.
*/
int counter = 0;
int total = 0;
void setup() {
// sets the serial port to 9600
Serial.begin(9600);
}
void loop() {
// read analog input pin 0
int reading = analogRead(0);
// add the reading to the total
total = total + reading;
// incrementing the counter
counter = counter + 1;
// if have already been done 10 readings...
if (counter >= 10) {
// set the counter to 0
counter = 0;
// calculate the average
int average = total / 10;
// send it to the serial port (as ASCII digits)
Serial.println(average, DEC);
// set the total to 0
total = 0;
}
// wait 1 ms for next reading
delay(100);
}
As one can now see in graph of the figure 3, the moments when the motor is turned on and off is now clearer.
|
Figure 3 |
The sketch can be improved to reject the values that are not within the expected range making use of several statistical criteria. After some investigation I found a statistical method easy to implement to reject the "bad" data, known as the
Chauvenet's criterion.
The implementation of the method can be seen in the following sketch
.
/*
Computes the average of a sample of N readings at intervals
of 1000/N ms from a ACS712 low current sensor connected to
the analog input pin 0 on Arduino board and print them to the
serial monitor.
This sketch uses the the Chauvenet's statistical criterion
for rejecting the bad readings.
*/
const int num_readings = 20;
// Chauvenet’s criterion for rejecting a reading
// http://people.ohio.edu/bayless/seniorlab/lecture1.ppt
// http://people.ohio.edu/bayless/seniorlab/chauvenet.pdf
// Consult the table of the pdf document to find the ratio
// of maximum acceptable deviation to precision index for
// this sampling.
const int mad = 2.24;
int readings[num_readings];
int index = 0;
void setup() {
// sets the serial port to 9600
Serial.begin(9600);
}
int average() {
int total = 0;
for(int i=0; i<num_readings; i++)
total = total + readings[i];
return total/num_readings;
}
float standard_deviation(int avg) {
int total = 0;
for(int i=0; i<num_readings; i++)
total = total + pow((avg - readings[i]), 2);
return sqrt(total/num_readings);
}
void loop() {
// read analog input pin 0
int reading = analogRead(0);
readings[index] = reading;
// incrementing the index
index = index + 1;
// if have already been done 10 readings...
if (index >= num_readings) {
// set the index to 0
index = 0;
// compute the average
int avg = average();
// compute the standard deviation
float std = standard_deviation(avg);
float madstd = mad * std;
float lowlimit = avg - madstd;
float highlimit = avg + madstd;
int count = 0;
int total = 0;
for(int i=0; i<num_readings; i++) {
// Check if the values of the readings are within the limits.
if(readings[i] >= lowlimit && readings[i] <= highlimit) {
total = total + readings[i];
count = count + 1;
}
}
// compute the new average
int newaverage = total/count;
// send it to the serial port (as ASCII digits)
Serial.println(newaverage, DEC);
}
// wait 1000/num_readings ms for next reading
delay(int(1000/num_readings));
}
The figure 4 shows the graph of the average variation of the readings after being analyzed with the Chauvenet's
statistical criterion.
|
Figure 4 |
When comparing with the graph of figure 3, we can see that there is not much difference between the two graphs. However, these statistical methods are useful because many sensors are very sensitive to external influences that may cause momentary readings outside of the expected values.
|
Figure 5 |
In the figure 5 we can see the circuit in operation connected to my Gentoo laptop. I lost a lot of time with this sensor but finally, I think I understand how I can use it.