2

I am a beginner when it comes to electronics, coding and things like that (this is practically the first time I have done anything like this), so when building an application that is supposed to vibrate a vibration motor with a strength based on the distance measurement made by the ultrasonic rangefinder, I bumped up with a problem.

The MCP 41010 digital potentiometer seems to let electricity through only when it is given a SPI.transfer(128). Any other number stops the flow of electricity completely.

I have tried some addresses such as 00, 0x00, 0x01 and 0x04 to replace the 0 and the result was the same. With addresses 0x11 and 0x08 the digital potentiometer didn't react at all.

In addition to the code I have here I have tried just copy-pasting some of the tutorials I found from the internet, for example this one Digital Potentiometer not fading LED without really understanding the commands formats thing all that well. With that code I got a vibration that didn't seem to fade in or fade out at all, so the problem remains (I lack a way to properly test that though).

So... what am I doing wrong and how to fix it?

Thank you!

enter image description here

Many tutorials were used when making the code.

#include <SPI.h>

int vcc = 2; // attach pin 2 to vcc
int trig = 3; // attach pin 3 to Trig
int echo = 4; // attach pin 4 to Echo
int gnd = 5; // attach pin 5 to GND

int shortest = 250;
int longest = 12000;

int CS = 10; // for digi pot


void setup() {

  SPI.begin ();
  pinMode (vcc,OUTPUT);
  pinMode (gnd,OUTPUT);
  pinMode (CS, OUTPUT); // for digi pot
  // initialize serial communication:
  Serial.begin(9600);

}

void loop()
{
  digitalWrite(vcc, HIGH);
  // establish variables for duration of the ping,
  // and the distance result in inches and centimeters:
  long duration;
  
  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(trig, OUTPUT);
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(5);
  digitalWrite(trig, LOW);
  
  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(echo,INPUT);
  duration = pulseIn(echo, HIGH);

  if (duration > 200 && duration < 220)
  // Limiting out an unwanted, randomly appearing distance measurement
  // made useless by later code though
    {
     Serial.print("Error ");
     Serial.print(duration);
     Serial.print("\n");
    
     return;
    }

   // Compressing the result of the distance measurement into the scale of 0 - 128
  if (duration < shortest) duration = shortest;
  if (duration > longest) duration = longest;
  duration = (1.0f-((float)(duration - shortest) / (float)(longest - shortest))) * 128;
  
  digitalWrite(CS, LOW);
  SPI.transfer(0); // 0x01 and 0x04 seem to "work" too. With 0x11 and 0x08 no voltage goes through
  SPI.transfer(duration); // sending a number from 0 to 128 to the digital potentiometer
  digitalWrite(CS, HIGH);
  
  Serial.print(duration); // printing the result of the measurement and calculations
  Serial.print("\n");

  delay(100);
}

1 Answer 1

3

Digital potentiometers are not a good choice for controlling the speed of a motor. They are designed only for very low current applications - things like setting offset points for op-amps and things like that - things where you would use a small trimmer pot rather than a large power rheostat.

Instead you should be controlling the motor using PWM and a transistor (here is a good tutorial).

But to help you understand the digital potentiometer and so you can work with it better:

Step one is always to read the datasheet. That details the SPI communication protocol for you so you can know what numbers mean what.

In this case the protocol is made up of two bytes - a command byte and a data byte.

The command byte is made up like this:

enter image description here

As you can see it's in two parts - a command and a potentiometer selector. So to set the resistance of potentiometer 0 you would need to craft a command byte that had the write command and the code for potentiometer 0. That would be 0b00010001 or 0x11 in hex. So your transaction would look like:

digitalWrite(CS, LOW);
SPI.transfer(0x11);
SPI.transfer(duration);
digitalWrite(CS, HIGH);

Another important part of the datasheet is the electrical characteristics. That is a table that tells you the minimum, typical and/or maximum values for different parameters. One important one here is the wiper current which it states as being allowed between -1mA and +1mA. That is the maximum current you are allowed to draw through the digital potentiometer before you risk damaging it. That is why it's not good for powering things like motors, no matter how small.

1
  • I agree with Majenko. What you probably need to control your vibrating motor is a MOSFET to handle the current, and possibly PWM output to manage whether you want weak or strong vibration.
    – Nick Gammon
    Jan 25, 2016 at 21:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.