Archive

Archive for the ‘Driving Motors’ Category

Arduino and Two Stepper Motors

May 30, 2015 16 comments

 

Two_Steppers

This project consist in moving two stepper motors “simultaneously”.
Really there is a loop where both motors are moved “one step at a time” to reach their final position.
5 Volts steppers with external power source are used.

 

Here is the video in YouTube:

Here is the Sketch:

—————-

/*------------------------------------------------------
Two_Steppers.ino     Arduining.com  30 MAY 2015

Driving two steppers concurrently with the Arduino Nano.
stepperX follows potentiometer on analog input 0.
stepperY follows potentiometer on analog input 1.
A timeout is used to turn off coils and save energy in battery
operated applications.

Hardware:
Arduino NANO.
Drivers: ULN2003A
Stepper Motors: 28BYJ48, 5VDC, step angle 5.625 °
                Gear reduction 64:1
                No-load starting frequency:> = 500PPS (4 rpm)
                Coil resistance 60 Ohms.               
 -----------------------------------------------------*/

#include <Stepper.h>

#define  STEPSREV    4096    // 64(fullsteps) * 64 (reduction ratio)
#define  SPEED       4       // motor speed (RPM)

#define  COIL_1X     11
#define  COIL_2X     9
#define  COIL_3X     10
#define  COIL_4X     8

#define  COIL_1Y     7
#define  COIL_2Y     5
#define  COIL_3Y     6
#define  COIL_4Y     4

#define  POT_X       0
#define  POT_Y       1                
#define  TIMEOUT     1000    //Turns off after 1 sec of inactivity.
#define  NOISE       8       //inmunity in steps because analog noisy readings.

// create the instances of the stepper class.
Stepper stepperX(STEPSREV, COIL_1X, COIL_2X, COIL_3X, COIL_4X);
Stepper stepperY(STEPSREV, COIL_1Y, COIL_2Y, COIL_3Y, COIL_4Y);

int potValX,potValY;           // potentiometers analog readings
int Xpos,Ypos;                 // Actual steppers positions(0-4096)->(0-360°)
int newXpos, newYpos;          // New steppers positions
unsigned long stampX, stampY;  // last move time stamped.

//============== functions ====================================================

//Read the potentiometers and map the reading to mach 360 degrees.
void readPots(){
  potValX = analogRead(POT_X);          // read POT_X value (0-1023).
  potValY = analogRead(POT_Y);          // read POT_Y value (0-1023).
  newXpos= map(potValX,0,1023,0,2047);  // Map pot X range to one stepper turn.
  newYpos= map(potValY,0,1023,0,2047);  // Map pot Y range to the stepper turn.
}
 
//-----------------------------------------------------------------------------
// Aproach stepperX to the newX position.
void aproachX(int newX){
  int Xdir = Xpos<newX ? 1 : -1;
  stepperX.step(Xdir);        // move one step in the Xdir direction.
  Xpos += Xdir;               // update Xpos.
  stampX = millis();          // stamp actual time.
  }

//-----------------------------------------------------------------------------
// Aproach stepperY to the newY position.
void aproachY(int newY){
  int Ydir = Ypos<newY ? 1 : -1;
  stepperY.step(Ydir);        // move one step in the Ydir direction.
  Ypos += Ydir;               // update Ypos.
  stampY = millis();          // stamp actual time.
  }

//-----------------------------------------------------------------------------
//Check for inactivity and turn off the steppers coils to save battery.
void CheckTimeout(){
  if((millis() - stampX) > TIMEOUT){   //Turn Off StepperX coils.
    digitalWrite(COIL_1X, LOW);
    digitalWrite(COIL_2X, LOW);
    digitalWrite(COIL_3X, LOW);
    digitalWrite(COIL_4X, LOW);
  }
  if((millis() - stampY) > TIMEOUT){   //Turn Off StepperY coils.
    digitalWrite(COIL_1Y, LOW);
    digitalWrite(COIL_2Y, LOW);
    digitalWrite(COIL_3Y, LOW);
    digitalWrite(COIL_4Y, LOW);
  }    
}


//=================== setup ===================================================
void setup(){
  stepperX.setSpeed(SPEED);  // set the X motor speed.
  stepperY.setSpeed(SPEED);  // set the Y motor speed.
  readPots();
  Xpos = newXpos;
  Ypos = newYpos;
}

//================= main loop =================================================
void loop(){
  readPots();
//if diference is greater than NOISE move steppers.
  if(abs(newXpos - Xpos)> NOISE) aproachX(newXpos);
  if(abs(newYpos - Ypos)> NOISE) aproachY(newYpos);

  CheckTimeout();   //check for inactivity.

}

 

—————-

 

 

 

 

 

Arduino Trinket and Gauge Stepper Motor

January 31, 2014 15 comments

Driving directly a stepper motor used for Vehicle’s Instrument Gauges.

wpid-20140131_232948.jpg

The motor must be removed during the Sketch Loading (disconnect from USB pins) .

wpid-IMG_20140131_235102.jpg

This kind of motors can be driven directly by the Trinket.
The motor follows the potentiometer.

IMG_0009

The Sketch is the same used in the “Arduino Driving a Micro Stepper Motor” in this blog, just change the pin mapping to use the Trinket .

https://arduining.com/2012/04/22/arduino-driving-a-micro-stepper-motor/

Change the definitions in “Gauge_Pot01.ino”:

#define  STEPS  720    // steps per revolution (limited to 315°)
#define COIL1  1
#define COIL2  3
#define COIL3  4
#define COIL4  0
#define POTIN  1

The YouTube video…

 

Arduino Trinket and RC Servo

January 26, 2014 1 comment

Testing SoftwareSerial library in the Trinket to drive the  7-Segment Serial Display COM-11441 (Sparkfun)
The potentiometer value was maped in the range 900 to 2100 microseconds to generate the servo control pulses.

IMG_0008

The Serial Display  shows the pulse duration in milliseconds.

wpid-20140126_233030.jpg

Using bit banging instead of SoftwareSerial saves more than 2K of program memory.

wpid-20140126_234312.jpg

The YouTube video:

Single Pixel Camera with Arduino Nano

July 16, 2013 3 comments

The idea of a camera using a single light detector always atracted my atention.
There are sophisticated applications using Compressive Imaging and single pixel cameras, but my objetive was more simple to implement.
Inspired by the project “A Low-Cost Single-Pixel Thermographic Camera”.
Using the following material:
-Pan and Tilt servo assebly from ServoCity.com (A smaller one would be enough)
-TEPT4400 light sensor from VISHAY.
-Arduino NANO.
-120nF polyester capacitor
-Breadboars, jumpers etc..

At first, some experiments to sense very low light intensity (we will use a pinhole to catch a very small area of the image).

TEPT4400_sch2

Using the Oscilloscope to observe the charge of the capacitor:

Charging

The following technic was implemented in the Arduino software:

Technique

This method is useful to increase the range of the light measured, but in this project only the gray area was used because the low light intensity and the short time to take the sample. Using a current amplifier to charge the capacitor may solve the problem (things to do).

The One Pixel Camera:

Camera_04Camera_05

The full Assembly:

Pic_01

The Arduino Nano is reading the light intensity and controlling the servos, a separated breadboard is used to feed the servos with an external 5V power adapter.

Capture_02

The 40×30 pixels  image is generated in Processing, the aplication is very simple. The Arduino sends  x ,y coordinates and the the light intensity of each position , Processing just paint each point of the image using a square of 8×8 (screen pixels) with a grey value in the range 0-255.

I want to share the simple code used in Processing:

/*Pro_Single_Pixel_01.pde
Arduining 7 JUL 2013
This Processing application plot the incoming value (0-255)
in the specified coordinates with a gray scale 8x8 pixels square.
The incoming characters at 9600 bauds have the following format:
xPos,yPos,value CR
xPos = x coordinate (1-40)
yPos = y coordinate (1-30)
value = gray scale value (0-255)
CR  ending with a carriage return character.
*/
import processing.serial.*;

Serial port; 

int xPos;
int yPos;
int value;

void setup(){
  println(Serial.list());               // Check COM port number and edit...
  String portName = Serial.list()[0];   // ...the index in Serial.list[]
  port = new Serial(this, portName, 9600);
  port.bufferUntil(10); 
  size(320,240);
  background(255);
}

void draw(){

}

void serialEvent(Serial _port){
  String input = port.readString(); 
  input = trim(input);
  String[] vars = split(input, ",");
  xPos = int(vars[0]);
  yPos = int(vars[1]);
  value = int(vars[2]);

  println(value);         // To see the received values.
  noStroke();
  fill(value);
  rect(xPos*8, yPos*8, 8, 8);
}

And this is the sketch used in the Arduino, the macros for direct port manipulation can be avoided in the final version but was useful to experiment with the charge-discharge circuit.

/*Ard_SinglePixelCam.ino

Arduining.com    06 JUL 2013  
Sketch used in the YouTube video "Single Pixel Camera with Arduino"
This code controls two servos to produce the scanning of the
single pixel camera.
The x and y position is sent with the corresponding light intensity.
Characters are sent at 9600 bauds with the following format:
xPos,yPos,value CR
xPos = x coordinate (1-40)
yPos = y coordinate (1-30)
value = gray scale value (0-255)
CR  ending with a carriage return character.
*/

#include <Servo.h> 

#define TILT_SERVO  7
#define PAN_SERVO   8

#define H_SIZE      40   // Horizontal picture elements.
#define V_SIZE      30   // Vertical picture elements.
#define SENSOR      0    // Light intensity sensor.
#define Xcenter     140  // X image center (Servo position in degrees)
#define Ycenter     35   // Y image center (Servo position un degrees)

//=====================================================================
//Definitions and variables used by ReadPixel() funtion
#define AnalogIn    0
#define Tcharge1    5000    //Delay microseconds before first Adquisition.
#define Tcharge2    20000   //Delay microseconds before second Adquisition.

//Macros to control the Light Sensor Circuit:
#define Discharge  {DDRD &= B00000011; DDRD |= B00001000; PORTD |= B00000000;}  //D3 output LOW.
#define Sense      {DDRD &= B00000011; DDRD |= B00000000; PORTD |= B00000000;}  //D3 as input.

//Variables
int first,second;

//=====================================================================
Servo servo_tilt;
Servo servo_pan;

//============== functions ============================================
//---------------------------------------------------------------------
void SendPixel(int xPos, int yPos, int value){
   Serial.print(xPos); Serial.print(","); Serial.print(yPos); Serial.print(","); Serial.println(value); 
}

//--------------------------------------------------------------------- 
void goto_origin(){
  servo_tilt.write( V_SIZE/2 + Ycenter ); // Tilt servo at top.
  servo_pan.write( Xcenter - H_SIZE/2 );  // Pan servo to left.
  delay(1000);                            // time to reach origin.
}

//--------------------------------------------------------------------- 
int ReadPixel(){
Sense
delayMicroseconds(Tcharge1);    //Delay to take the first value.
first= analogRead(AnalogIn);    //first value is taken.
delayMicroseconds(Tcharge2);    //Delay to take the second value.
second= analogRead(AnalogIn);   //second value is taken.
Discharge
if (first<200)first= second;    //if first is under 200, second will be under 1024.
else first = first * 5 ;        //if first is over 200, first*5 will be used.
first = map(first, 0, 60, 0, 255); //map was adjusted for the light conditions.
return first;
}

//=============== setup ================================================
void setup() 
{ 
  servo_tilt.attach(TILT_SERVO); 
  servo_pan.attach(PAN_SERVO);
  Serial.begin(9600);

  ReadPixel();      //Read and discard it (Discharge for next read).//================= main loop =========================================
void loop(){

  goto_origin();

  for (int y=0 ; y<V_SIZE ; y++) { 

    servo_tilt.write(Ycenter + V_SIZE/2 -y );
    delay(50);                              // time to reach position.

     for ( int x=0 ; x<H_SIZE ; x++) {      // Scan from Left to Right.
      servo_pan.write(Xcenter - H_SIZE/2 + x);
      delay(50);                            // time to reach position.

      SendPixel(x, y, ReadPixel());      
    }
    y++;
    servo_tilt.write(Ycenter + V_SIZE/2 - y);
    delay(50);                              // time to reach position.

      for ( int x=H_SIZE-1 ; x>=0 ; x--) {  // Scan from Right to Left.
      servo_pan.write(Xcenter - H_SIZE/2 + x);     
      delay(50);                            // time to reach position.

      SendPixel(x, y, ReadPixel());
    }

  }
}

Next steps:

-Increase the resolution and speed using stepper motors with gear reduction.

-Increase the sensibility and reduce the adquisition time using an Operational Amplifier as current amplifier in the charge circuit.

-Improve the resolution of the image using a smaller hole and a small box instead of a tube to capture the light (this is to eliminate the light reflections inside the cylinder).

-Hope to receive more ideas about this project, a well done Single Pixel Camera open the possibilities of experimenting with image processing algorithms.

The Youtube video shows the camera in action:

LaunchPad Energia and Stepper Motor

July 10, 2013 15 comments

Using the MSP430 LaunchpPad and Energia to control a stepper motor.
For this project a former Arduino’s project was used.

Moving_USB_2

First thing was to make the stepper and driving board as a single assembly, this make it easier to experiment with it in the future.

Making

Some wiring to connect the Launchpad (3.6 Volts) was done.
The stepper motor can be powered from the USB Voltage (5 volts at TP1) or
an external power supply. In this case I used both for testing purposes, the USB power and a Power adapter.

Make_13

20120924_164239

The connections are shown as an image to make it easier for all.

Wiring

And now the code:

/*------------------------------------------------------
StepperPot_11
Arduining.com 13 APRIL 2013

A stepper motor follows a potentiometer on analog input 5.
A software low-pass filter is used to reduce the noise in the analog reading.
After 3 seconds of inactivity the motor coils are turned OFF to save energy.
The RED_LED is used to signal when the stepper is powered.

Hardware:
LaunchPad with MSP430G2553.
Driver: ULN2003A
Stepper Motor:  28BYJ48, 5VDC, step pangle 5.625 °
                Gear reduction 64:1
                No-load starting frequency:> = 500PPS (4 rpm)
                Coil resistance 60 Ohms.               
 -----------------------------------------------------*/

#include <Stepper.h>

// change this to the number of steps on your motor
#define  STEPSREV    4096    // 64(fullsteps) * 64 (reduction ratio)
#define  COIL1       14
#define  COIL2       12
#define  COIL3       13
#define  COIL4       11
#define  POT         A5
#define  ENER        RED_LED
#define  TIMEOUT     3000    //Turns off after 3 secs of inactivity.

// create an instance of the stepper class, specifying
// the number of steps per revolution and pins atached to motor coils.
Stepper myStepper(STEPSREV, COIL1, COIL2, COIL3, COIL4);
int PotVal;
int LastPotVal= 0 ;          // To implement a software Low-Pass-Filter
int pos = 0;              // stepper position(0-4096)->(0-360°)
unsigned long stamp = 0;  // last move time stamped.

void setup()
{
  myStepper.setSpeed(4);  // set the motor speed to 4 RPM
  pinMode(ENER, OUTPUT);  // status led (coils energized).
//  Serial.begin(9600);   //for debuging.
}

void loop(){

  PotVal = analogRead(POT);       // Potentiometer value range 0-1023

  PotVal= map(PotVal,0,1023,0,2047);      // Map pot range in the stepper range.
  PotVal= PotVal * 0.1 + LastPotVal * 0.9 ;  // Filtering to reduce noise.
  LastPotVal= PotVal;

//  Serial.print(Val);              // For debuging.
//  Serial.print("   ");            //    "
//  Serial.println(pos);            //    "
//  delay(500);                     //    "  

  if(abs(PotVal - pos)> 4){              //if diference is greater than 4 steps.
      if((PotVal - pos)> 0){
          digitalWrite(ENER, HIGH);   //Motor energized.     
          myStepper.step(1);           // move one step to the right.
          pos++;
          }
      if((PotVal - pos)< 0){
          digitalWrite(ENER, HIGH);   //Motor energized.
          myStepper.step(-1);            // move one step to the left.
          pos--;
          }
      stamp = millis();               // stamp actual time.
      }
  else {      
      if((millis() - stamp) > TIMEOUT){   //Turn Off coils after TIMEOUT.
          digitalWrite(COIL1, LOW);
          digitalWrite(COIL2, LOW);
          digitalWrite(COIL3, LOW);
          digitalWrite(COIL4, LOW);
          digitalWrite(ENER, LOW);    //Motor de-energized.
          }    
      } 

}

See in YouTube this experiment:

Floating Ball With Arduino

May 7, 2013 2 comments

Ok, I’m working in something interesting…

IMG_0002

All the hardware is working.

togrther

Software routines to control the FAN (PWM) and reading the IR Range Sensor GP2D120 (from SHARP) also working….

GP2D120_ref

Now, the problem… closing the loop…. 🙂

 

 

Arduino PWM and Mini Motor

April 8, 2013 Leave a comment

Driving a vibrating motor directly from an Arduino is possible without burning it.

Using a 75 Ohms series resistor the current can be maintained under 40 milliams (ATMEGA238 max. limit).

The motor speed can be controlled using a Potentiometer to adjust the PWM signal.

A Photoswitch detects the slot in the wheel  for revolutions counting.

Minimot_GIF

The yellow Led  toggles every 30 revolutions.

Removing the offset weight, a no easy task.

Minimot_mass

Some Laser Cutting was done before put together all parts.

Disc_1_slotSoportes

How was connected to the Arduino pins:

Minimot_sch_

The final Assembly:

Final_Ass

The sketch used in the YouTube demostration:

/*------------------------------------------------------------------------------
  MiniMot_10
  Arduining.com  05 APRIL 2013
  
      The excentric mass is replaced by a disk in a Mini Vibrating Motor.
      A Motor Revolutions Counter is implemented using a photoswitch.   
      The Motor speed is controlled with a potentiometer.
      A led is toggled every 30 revolutions to show the motor speed.
      The PWM value is transmited to the Serial monitor.
  
      Arduino (ATMEGA328)drives directly the Motor, a series resistor
      of 75 ohms limits the current to 40 milliamps.
     
 -----------------------------------------------------------------------------*/
#define  MOT1    9        //Pin directly connected to the Motor.
#define  MOT2    10       //Pin connected to the Motor trhought a 75 Ohms resistor.
#define  LED     7        //Pin connected to the LED.
#define  POT     0        //Analog input for the potentiometer.
#define  PhotoSwitch  8   //Pin connected to the photoswitch.

#define  TURNS   30       //Number of turns to toggle the LED.

int Counter;              //Revolutions counter.
int PWMval;               //PWM Value to control the motor speed.
boolean WaitSlot= true;   //Flag used for slot detection.
boolean LedState= 0;      //1= on , 0= off

void setup() {                 
  pinMode(LED, OUTPUT);
  pinMode (PhotoSwitch, INPUT);
  Serial.begin(9600);
  analogWrite(MOT2, 0);    //pin 2 of the motor grounded.
}

void loop()
{
  PWMval=analogRead(POT)/4;  //read potentiometer.
  analogWrite(MOT1,PWMval);  //set the motor speed.

  if (!digitalRead(PhotoSwitch) && WaitSlot){  //slot detection!
    Counter++;
    WaitSlot=false;
    if (Counter == TURNS){
      LedState = !LedState;        // toggle the Led state.
      digitalWrite(LED,LedState);
      Serial.println(PWMval);
      Counter=0;                  //Reset the revolutions counter.
      }
    }

  else if (digitalRead(PhotoSwitch)) WaitSlot= true;  //No slot.

 }
Categories: Driving Motors