Digital signal processing and filtering – motor current sensing

Posted by

After a recent post on current sensing, I talked to a couple of friends at NYC Resistor (my usual sounding board) and got some great advice (as usual).

One thing I didn’t remember was the difference between passive and active filtering, and that it might take more than a simple RC circuit to filter out the noise I was seeing. I was pointed to a few good reads:
http://ww1.microchip.com/downloads/en/devicedoc/41233A.pdf
http://www.maxim-ic.com/app-notes/index.mvp/id/1762
http://www.swarthmore.edu/NatSci/echeeve1/Ref/DataSheet/IntroToFilters.pdf

But before I got too far into digital signal processing land and making hardware based 2nd or 3rd order filters, I wanted to see if there was a better way. I got in touch with JD Warren, one of authors of Arduino Robotics. One of the projects in the book used a custom built motor driver with a hall effect current sensor. I’ve shied away from these until now because they seemed to be more voodoo than the more intuitive current sensing resistor method, but after reading parts of his book and talking with JD, I ordered up some ACS712s and some surface mount to breadboard adapters from Digikey. He always had good luck with them so hopefully that luck rubs off and they’ll be less noisy than the method I’m using now.

I also did some more research and found that the L298 h-bridge, basically the next step up from the L293 that comes on the Adafruit Motor Shield, has current sensing already built in! Luckily both the Sparkfun Ardumoto Shield and the Arduino Motor Shield use this h-bridge, but only the Arduino shield has those pins broken out. So I ordered both, figuring I could hack the Sparkfun one by cutting the traces and soldering some little jumper wires if necessary (I studied the schematics for quite a while before convincing myself this would be possible). From what I can gather from the datasheet, I still need to add a current sensing resistor, and it uses basically the same method I was using before, but something about the integrated solution I suppose could make a difference. We’ll see.

First Test: Arduino Motor Shield
The documentation on this shield is a little spotty, but from the schematic and Eagle files, I figured out that the current sensing resistors were already integrated along with an op-amp that presumably amplifies the tiny voltage drop. The hardware page says the resolution is 1.65 A/V, so it looks like they did the math already on what resistors and what gain was used to get an actual current rating from a detectable voltage drop. So I wrote up some code (below) and after a little tweaking got this:

Isn’t that beautiful?!? A little jumpy still but might be good. I think it’s time to swap this in where the Adafruit Shield is now and see what happens with the robot arm.

[code lang=”arduino”]
/*
Curent sensing with the Arduino Motor Shield: http://arduino.cc/it/Main/ArduinoMotorShieldR3

One small DC motor attached to screw terminal block A
External power from a 4 x AA batter pack

CC-BY-SA
by Dustyn Roberts
6/12/2012
*/

// declare pins used on channel A
int directionPin = 12;
int pwmPin = 3;
int brakePin = 9;
int currentPin = A0;

int switchPin = 2; // motor on/off switch
// connect one side of switch to power, the other to ground through a 10k resistor
// read the switch state where the switch and resistor meet into digital pin 2
// similar to this lab: http://itp.nyu.edu/physcomp/Labs/DigitalInOut

// constants
float volt_per_amp = 1.65; // resolution according to hardware page

// variables
float currentRaw; // the raw analogRead ranging from 0-1023
float currentVolts; // raw reading changed to Volts
float currentAmps; // Voltage reading changed to Amps

void setup() {
pinMode(directionPin, OUTPUT);
pinMode(pwmPin, OUTPUT); // necessary according to forum post http://arduino.cc/forum/index.php/topic,89468.0.html
Serial.begin(9600);
}

void loop() {
// read the switch input:
if (digitalRead(switchPin) == HIGH) {
// if the switch is closed:
digitalWrite(pwmPin, HIGH); // necessary according to forum post http://arduino.cc/forum/index.php/topic,89468.0.html
digitalWrite(directionPin, HIGH);
}
else {
// if the switch is open:
digitalWrite(pwmPin, LOW); // necessary according to forum post http://arduino.cc/forum/index.php/topic,89468.0.html
digitalWrite(directionPin, LOW);
}

currentRaw = analogRead(currentPin);
currentVolts = currentRaw *(5.0/1024.0);
currentAmps = currentVolts/volt_per_amp;

Serial.println(currentAmps);
}

[/code]

10 comments

  1. You also want to have a stable Vref voltage. The Leonardo’s Vref pin is connected to a low-pass filter which is connected to 5V. I have found that it needs more capacitance to be “stable.”

  2. Here’s some code to test the noise on your Vref pin. The best result comes from using the on-board linear regulator. The 5 volts from the USB plug tends to be noisy. Your environment may be different, so I would run the “sketch” to check the noise level. I’ve tested the code on the Uno and Leonardo boards.

    [sourcecode language=”cpp”]
    void setup() {
    #if defined(USBCON)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
    #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
    #endif
    delay(2); // Wait for Vref to settle
    Serial.begin(9600);
    }

    uint16_t min_reading=1023;
    uint16_t max_reading=0;
    uint16_t reading;

    void loop() {
    if (millis() % 1000) {
    ADCSRA |= _BV(ADSC); // start convertion
    loop_until_bit_is_clear(ADCSRA,ADSC);
    reading = ADCL;
    reading |= ADCH<<8;
    min_reading = min(min_reading, reading);
    max_reading = max(max_reading, reading);
    } else {
    Serial.print ("Vref noise: ");
    Serial.print ((max_reading – min_reading) * 4.88);
    Serial.println(" mV");
    min_reading=1023;
    max_reading=0;
    delay(1);
    }
    }
    [/sourcecode]

  3. однажды, бесцельно листая страницы своего телефона, я наткнулся на челябинский новостной сайт mir74.ru, и с тех пор он стал желанным дополнением к моей повседневной жизни. Открыв для себя mir74.ru, я стал более информированным о текущих событиях в моем городе, всегда в курсе местных новостей и нашел надежный источник развлечений и досуга в своем районе.

    mir74.ru помог мне быть более информированным о текущих событиях в моем городе. Сайт держит меня в курсе последних событий в Челябинске, как только они происходят, и своевременно освещает важные события, такие как выборы или чрезвычайные ситуации, которые иначе остались бы незамеченными без этого ресурса. Кроме того, он дает мне доступ к информации о таких вещах, как закрытие дорог или задержки в движении, о которых в противном случае я мог бы и не знать — благословение для человека, который часто ездит на работу!

    mir74 помогает мне следить за местными новостями, чтобы я всегда был в курсе того, что происходит в регионе; от политики до спорта, культуры и развлечений — здесь есть что-то для всех! Сайт не только предоставляет точную информацию о национальных новостях, но и содержит более локализованные статьи, которые могут быть невероятно полезны при принятии решений, основанных на том, что происходит прямо там, где я живу.

    в заключение хочу сказать, что открытие сайта mir74.ru стало для меня открытием, которое положительно повлияло на мою повседневную жизнь — от того, что я стал более осведомленным о текущих событиях до того, что я всегда в курсе местных новостей и нахожу надежные источники развлечений поблизости! Это бесценный ресурс для всех, кто живет или даже приезжает в Челябинск; вы не пожалеете, если сами его посмотрите!

  4. Hello, I realize this is an old post (very old) but if you get this message, I wonder if you would could help me a bit. I have the same set up as you I think, Arduino Uno, Motor Shield Rev 3 and am driving size 130 DC motor via pwm as per Motor Shield documents. I want to sense the current, but I get crazy numbers, its clear that at low duty cycles for the pwm the reading for A0 is usually 0, and then other numbers, as it may only be reading current when the pwm voltage is on. I cant see how I could make the graph you have made here, but I would like to. Any help would be appreciated. Steven Lightfoot Feb 4 2024.

Leave a Reply to mkwired Cancel reply

Your email address will not be published. Required fields are marked *