Pages: [1]   Go Down
Author Topic: Help running servo using encoder  (Read 1040 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello. I am building a simple ruler using ALPS STEC12E08 encoder, regular 5V servo, and 20x4 LCD. I have adapted code from other websites and users and using for my project. The problem the lcd is displaying the correct values, but I do not know how to implement the servo into the project. I need the servo to spin corresponding to the encoder value. So for example, if you spin encoder and it says one, servo should move one degree to whatever side you have spinned the encoder. PLease help me implement the servo into the project. Thank you.
Code:
#include <LiquidCrystal.h>
#include <Servo.h>
#define ENC_A 14
#define ENC_B 15
#define ENC_PORT PINC

// Connections:
// rs (LCD pin 4) to Arduino pin 12
// rw (LCD pin 5) to Arduino pin 11
// enable (LCD pin 6) to Arduino pin 10
// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
//Servo myservo;  // create servo object to control a servo
// a maximum of eight servo objects can be created

int backLight = 13;    // pin 13 will control the backlight
//int pinMode = 0;  // analog pins 0 and 1 used to connect encoder
//int pos = 0;  //variable to read the value from analog pins


void setup() //code to execute once at the beginning
{
 // myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  pinMode(ENC_A, INPUT);
  digitalWrite(ENC_A, HIGH);
  pinMode(ENC_B, INPUT);
  digitalWrite(ENC_B, HIGH);
  Serial.begin (115200);
  Serial.println("Start");
  pinMode(backLight, OUTPUT); // LCD Code begins
  digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
  lcd.begin(16,2);              // columns, rows.  use 16,2 for a 16x2 LCD   lcd.clear();                  // start with a blank screen
  lcd.setCursor(0,0);           // set cursor to column 0, row 0 (the first [size=10][/size]row)
  lcd.print("Paul Ulezko Ruler");    // change this text to whatever you like. keep it clean.
  //lcd.setCursor(0,1);           // set cursor to column 0, row 1
  //lcd.print("Lab 4 Ruler");
  
  // if you have a 4 row LCD, uncomment these lines to write to the bottom rows
  // and change the lcd.begin() statement above.
  //lcd.setCursor(0,2);         // set cursor to column 0, row 2
  //lcd.print("Row 3");
  //lcd.setCursor(0,3);         // set cursor to column 0, row 3
  //lcd.print("Row 4");
}

void loop() //executed over and over again
{
  static uint8_t counter = 0;      //this variable will be changed by encoder input
 int8_t tmpdata;
 /**/
  tmpdata = read_encoder();
  if( tmpdata ) {
    Serial.print("Counter value: ");
    Serial.println(counter, DEC);
    counter += tmpdata;
    lcd.setCursor(0,1);           // set cursor to column 0, row 1
    lcd.print("Counter value: ");
    lcd.setCursor(0,2);         // set cursor to column 0, row 2
    lcd.print(counter, DEC);
  
   }
}
  
/* returns change in encoder state (-1,0,1) */
int8_t read_encoder()
{
  int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_AB = 0;
  /**/
  old_AB <<= 2;                   //remember previous state
  old_AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_AB & 0x0f )]);
}
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 653
Posts: 50912
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The first thing you need to decide is what will happen when the encoder goes over 179 (or whatever the upper limit on your servo is) or below 0.

If you set the servo position to counter in your code, and constrain (http://arduino.cc/en/Reference/Constrain) the servo position, you will be able to simply Servo::write() the value to the servo.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have tried implementing the suggested, however, the counter numbers are not diplaying from 1 to 255 anymore and the servo begins to infinite spinning when I turn encoder knob.
Code:
#include <LiquidCrystal.h>
#include <Servo.h>
#define ENC_A 14
#define ENC_B 15
#define ENC_PORT PINC

// Connections:
// rs (LCD pin 4) to Arduino pin 12
// rw (LCD pin 5) to Arduino pin 11
// enable (LCD pin 6) to Arduino pin 10
// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
Servo myservo;  // create servo object to control a servo
// a maximum of eight servo objects can be created

int backLight = 13;    // pin 13 will control the backlight
//int pinMode = 0;  // analog pins 0 and 1 used to connect encoder
int sensVal = 0;  //variable to read the value from analog pins
int val = 0;


void setup() //code to execute once at the beginning
{
  myservo.attach(8);  // attaches the servo on pin 9 to the servo object
  pinMode(ENC_A, INPUT);
  pinMode(ENC_A, INPUT);
  digitalWrite(ENC_A, HIGH);
  pinMode(ENC_B, INPUT);
  digitalWrite(ENC_B, HIGH);
  Serial.begin (115200);
  Serial.println("Start");
  pinMode(backLight, OUTPUT); // LCD Code begins
  digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
  lcd.begin(20,4);              // columns, rows.  use 16,2 for a 16x2 LCD, etc.
  lcd.clear();                  // start with a blank screen
  lcd.setCursor(0,0);           // set cursor to column 0, row 0 (the first row)
  lcd.print("Paul Ulezko Ruler");    // change this text to whatever you like. keep it clean.
  //lcd.setCursor(0,1);           // set cursor to column 0, row 1
  //lcd.print("Lab 4 Ruler");
  
  // if you have a 4 row LCD, uncomment these lines to write to the bottom rows
  // and change the lcd.begin() statement above.
  //lcd.setCursor(0,2);         // set cursor to column 0, row 2
  //lcd.print("Row 3");
  //lcd.setCursor(0,3);         // set cursor to column 0, row 3
  //lcd.print("Row 4");
}

void loop() //executed over and over again
{
  static uint8_t counter = 0;      //this variable will be changed by encoder input
 int8_t tmpdata;
 /**/
  tmpdata = read_encoder();
  if( tmpdata ) {
    Serial.print("Counter value: ");
    Serial.println(counter, DEC);
    counter += tmpdata;
    lcd.setCursor(0,1);           // set cursor to column 0, row 1
    lcd.print("Counter value: ");
    lcd.setCursor(0,2);         // set cursor to column 0, row 2
    lcd.print(counter, DEC);
   // sensVal = constrain(sensVal, 10, 150);
    val = digitalRead(ENC_A);    // reads the value of the eno (value between 0 and 1023)
    val = digitalRead(ENC_B);
    val = constrain(val, 10, 180);
    //val = map(val, 0, 1023, 0, 179);     // scale it to use it with the servo (value between 0 and 180)
    myservo.write(val);                  // sets the servo position according to the scaled value
    delay(15);                           // waits for the servo to get there

  
   }
}
  
/* returns change in encoder state (-1,0,1) */
int8_t read_encoder()
{
  int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_AB = 0;
  /**/
  old_AB <<= 2;                   //remember previous state
  old_AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_AB & 0x0f )]);
}
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 653
Posts: 50912
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
   val = digitalRead(ENC_A);    // reads the value of the eno (value between 0 and 1023)
    val = digitalRead(ENC_B);
    val = constrain(val, 10, 180);
    //val = map(val, 0, 1023, 0, 179);     // scale it to use it with the servo (value between 0 and 180)
    myservo.write(val);                  // sets the servo position according to the scaled value
The first digitalRead function returns HIGH (1) or LOW(0). The second one does the same, overwriting the value in val.

Constrain then always returns 10.

Quote
and the servo begins to infinite spinning
Then, you haven't got a servo. You have an electric motor in a servo housing. That is not what you said you had up front.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am using Vex motor module and it has signal wire (PWM), power, and ground.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26631
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
it has signal wire (PWM),
If it really is PWM, then feeding it PPM from the servo library isn't going to give good results.
PPM is effectively very low duty-cycle (5 - 10%) PWM.

Can you post the specs of the "Vex motor module", please?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Technical Specifications.Kit Contents (1)VEX continuous rotation motor
(1)VEX motor gear set (4 total gears, 1 replacement for each gear inside)
(2)6-32 x 1/4" Screws
(2)6-32 x 1/2" Screws
(1)Clutch
(1)Clutch Post
(1)Inventor's Guide Insert
 
Downloads & Docs Inventor's Guide - Motor
Inventor's Guide - Motion
VEX Robot Speed Chart - Spur Gear Reductions
VEX Robot Speed Chart - Chain Reductions
VEX Robot Speed Chart - High Strength Chain Reductions
Compatibility All VEX Microcontrollers.
All VEX Square Shafts 0.125" (3.2mm)  
Specifications Free Speed:100 rpm @ 7.5 volts
Stall Torque:6.5 in-lbs
Voltage:4.4 - 9.1 Volts (Motor life will be reduced operating outside this range)
PWM Input:1ms - 2ms will give full reverse to full forward, 1.5ms is neutral
Dead Band:1.47ms - 1.55m
Black Wire:Ground
Orange Wire:Power
White Wire:PWM signal

Note: Performance varies slightly due to variations in manufacturing.  
Weight Motor0.096 lbs (43.5 grams)
6-32x1/4" Screw0.0014 lbs (0.617 grams)
6-32x1/2" Screw0.00209 lbs (0.948 grams)
Clutch0.007 lbs (3.17 grams)
Actual weight one item (no packaging)
 
http://www.vexrobotics.com/products/accessories/motion/276-2163.html
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

After working a whole day on this project's code, I somewhat figure out the problem. The anlaog value from the encoder had to be sent to the Vex motor module. However, even so the servo moves to the encoder without infinite loop anymore, it still has huge values due to the code bellow. Special thanks to who tried to help me.
Code:
pulse = map(analogValue,0,1023,minPulse,maxPulse);
Logged

Pages: [1]   Go Up
Jump to: