Show Posts
Pages: [1]
1  Topics / Robotics / Re: VNH5019 Motor Driver - Arduino Mega 2560 - Help needed on: November 18, 2012, 05:36:33 am
To get a PWM frequency of 20kHz as opposed to the maximum of an 8-bit timer. Pololu have developed a library specific to the Arduino Mega for all those interested.

http://forum.pololu.com/viewtopic.php?f=15&t=6139

2  Topics / Robotics / VNH5019 Motor Driver - Arduino Mega 2560 - Help needed on: November 15, 2012, 10:12:50 am
Hi,

I am having problems regarding the connection between the Arduino Mega 2560 and the Motor Driver VNH5019. I am trying to connect the Motor Driver to Timer 3 (that is pins 3&5 on the Arduino Mega),in order to use the 16-bit timer instead of the 8-bit timer which is connected to pins 9&10 which is the default connection used. I used these threads http://arduino.cc/forum/index.php?topic=77168.0 & http://forum.pololu.com/viewtopic.php?f=15&t=5806&p=27874&hilit=vnh5019#p27874 but have not been able to get both motors working.
I was previously using an Uno with the Motor Driver and did not have any problems since the 16-bit timer is connected to pins 9&10 on the Uno thus able to get the required PWM frequency (20kHz).
The motors I am using are: http://www.pololu.com/catalog/product/1103.
My set up is:
2 motors connected to the Mega via the Motor Driver powered by a 12V laptop charger which does not seem to have any problems.The connections I have are:

Digital 13      M1INA            Motor 1 direction input A
Digital 4       M1INB             Motor 1 direction input B
Digital 6       M1EN/DIAG      Motor 1 enable input/fault output
Digital 7       M2INA             Motor 2 direction input A
Digital 8       M2INB             Motor 2 direction input B
Digital 3       M1PWM           Motor 1 speed input
Digital 5       M2PWM           Motor 2 speed input
Digital 12     M2EN/DIAG      Motor 2 enable input/fault output
Analog 0       M1CS              Motor 1 current sense output
Analog 1       M2CS              Motor 2 current sense output


The header file is:

Code:
#ifndef DualVNH5019MotorShield_h
#define DualVNH5019MotorShield_h

#include <Arduino.h>

class DualVNH5019MotorShield
{
  public:
    // CONSTRUCTORS
    DualVNH5019MotorShield(); // Default pin selection
    DualVNH5019MotorShield(unsigned char INA1, unsigned char INB1, unsigned char EN1DIAG1, unsigned char CS1,
                           unsigned char INA2, unsigned char INB2, unsigned char EN2DIAG2, unsigned char CS2); // User-defined pin selection.
  
    // PUBLIC METHODS
    void init(); // Initialize TIMER 1 (or timer 3 for mega) set the PWM to 20kHZ
    void setM1Speed(int speed); // Set speed
    void setM2Speed(int speed); // Set speed
    void setSpeeds(int m1Speed, int m2Speed); // Set speed for both M1 and M2
    void setM1Brake(int brake); // Brake M1
    void setM2Brake(int brake); // Brake M2
    void setBrakes(int m1Brake, int m2Brake); // Brake both M1 and M2
    unsigned int getM1CurrentMilliamps(); // Get current reading
    unsigned int getM2CurrentMilliamps(); // Get current reading
    unsigned char getM1Fault(); // Get fault reading
    unsigned char getM2Fault(); // Get fault reading
  
  private:
    unsigned char _INA1;
    unsigned char _INB1;
  /*#if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
    static const unsigned char _PWM1 = 9;
    static const unsigned char _PWM2 = 10;
  #endif*/
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    static const unsigned char _PWM1 = 3;
    static const unsigned char _PWM2 = 5;
  #endif
    unsigned char _EN1DIAG1;
    unsigned char _CS1;
    unsigned char _INA2;
    unsigned char _INB2;
    unsigned char _EN2DIAG2;
    unsigned char _CS2;  
};
#endif

while the .cpp file is:
Code:
#include "DualVNH5019MotorShield.h"

// Constructors

DualVNH5019MotorShield::DualVNH5019MotorShield()
{
  //Pin map
  _INA1 = 13;
  _INB1 = 4;
  _EN1DIAG1 = 6;
  _CS1 = A0;
  _INA2 = 7;
  _INB2 = 8;
  _EN2DIAG2 = 12;
  _CS2 = A1;
}

DualVNH5019MotorShield::DualVNH5019MotorShield(unsigned char INA1, unsigned char INB1, unsigned char EN1DIAG1, unsigned char CS1,
                                               unsigned char INA2, unsigned char INB2, unsigned char EN2DIAG2, unsigned char CS2)
{
  //Pin map
  //PWM1 and PWM2 cannot be remapped because the library assumes PWM is on timer1
  _INA1 = INA1;
  _INB1 = INB1;
  _EN1DIAG1 = EN1DIAG1;
  _CS1 = CS1;
  _INA2 = INA2;
  _INB2 = INB2;
  _EN2DIAG2 = EN2DIAG2;
  _CS2 = CS2;
}

// Public Methods
void DualVNH5019MotorShield::init()
{
// Define pinMode for the pins and set the frequency for timer1.

  pinMode(_INA1,OUTPUT);
  pinMode(_INB1,OUTPUT);
  pinMode(_PWM1,OUTPUT);
  pinMode(_EN1DIAG1,INPUT);
  pinMode(_CS1,INPUT);
  pinMode(_INA2,OUTPUT);
  pinMode(_INB2,OUTPUT);
  pinMode(_PWM2,OUTPUT);
  pinMode(_EN2DIAG2,INPUT);
  pinMode(_CS2,INPUT);
 // #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
  // Timer 1 configuration
  // prescaler: clockI/O / 1
  // outputs enabled
  // phase-correct PWM
  // top of 400
  //
  // PWM frequency calculation
  // 16MHz / 1 (prescaler) / 2 (phase-correct) / 400 (top) = 20kHz
 // TCCR1A = 0b10100000;
 // TCCR1B = 0b00010001;
 // ICR1 = 400;
 // #endif
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  TCCR3A = 0b10100000; // Mega pin 5
  TCCR3C = 0b00010001; // Mega pin 3
  ICR3 = 400;
  #endif
}
// Set speed for motor 1, speed is a number betwenn -400 and 400
void DualVNH5019MotorShield::setM1Speed(int speed)
{
  unsigned char reverse = 0;
 
  if (speed < 0)
  {
    speed = -speed;  // Make speed a positive quantity
    reverse = 1;  // Preserve the direction
  }
  if (speed > 400)  // Max PWM dutycycle
    speed = 400;
//  #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
//  OCR1A = speed;
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  OCR3A = speed;
//  #else
//  analogWrite(_PWM1,speed * 51 / 80);
  #endif
  if (reverse)
  {
    digitalWrite(_INA1,LOW);
    digitalWrite(_INB1,HIGH);
  }
  else
  {
    digitalWrite(_INA1,HIGH);
    digitalWrite(_INB1,LOW);
  }
}

// Same as motor 1
void DualVNH5019MotorShield::setM2Speed(int speed)
{
  unsigned char reverse = 0;
 
  if (speed < 0)
  {
    speed = -speed;  // make speed a positive quantity
    reverse = 1;  // preserve the direction
  }
  if (speed > 400)  // Max
    speed = 400;
//  #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
 // OCR1B = speed;
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  OCR3C = speed;
 // #else
 // analogWrite(_PWM2,speed * 51 / 80);
  #endif
  if (reverse)
  {
    digitalWrite(_INA2,LOW);
    digitalWrite(_INB2,HIGH);
  }
  else
  {
    digitalWrite(_INA2,HIGH);
    digitalWrite(_INB2,LOW);
  }
}

// Set speed for motor 1 and 2
void DualVNH5019MotorShield::setSpeeds(int m1Speed, int m2Speed)
{
  setM1Speed(m1Speed);
  setM2Speed(m2Speed);
}

// Brake motor 1, brake is a number between 0 and 400
void DualVNH5019MotorShield::setM1Brake(int brake)
{
  // normalize brake
  if (brake < 0)
  {
    brake = -brake;
  }
  if (brake > 400)  // Max brake
    brake = 400;
  digitalWrite(_INA1, LOW);
  digitalWrite(_INB1, LOW);
 // #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
 // OCR1A = brake;
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  OCR3A = brake;
 // #else
 // analogWrite(_PWM1,brake * 51 / 80);
  #endif
}

// Same as motor 1
void DualVNH5019MotorShield::setM2Brake(int brake)
{
  // normalize brake
  if (brake < 0)
  {
    brake = -brake;
  }
  if (brake > 400)  
    brake = 400;
  digitalWrite(_INA2, LOW);
  digitalWrite(_INB2, LOW);
//  #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
 // OCR1B = brake;
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  OCR3C = brake;
 // #else
 // analogWrite(_PWM2,brake * 51 / 80);
  #endif
}

// Brake motor 1 and 2, brake is a number between 0 and 400
void DualVNH5019MotorShield::setBrakes(int m1Brake, int m2Brake)
{
  setM1Brake(m1Brake);
  setM2Brake(m2Brake);
}

// Return motor 1 current value in milliamps.
unsigned int DualVNH5019MotorShield::getM1CurrentMilliamps()
{
  // 5V / 1024 ADC counts / 144 mV per A = 34 mA per count
  return analogRead(_CS1) * 34;
}

// Return motor 2 current value in milliamps.
unsigned int DualVNH5019MotorShield::getM2CurrentMilliamps()
{
  // 5V / 1024 ADC counts / 144 mV per A = 34 mA per count
  return analogRead(_CS2) * 34;
}

// Return error status for motor 1
unsigned char DualVNH5019MotorShield::getM1Fault()
{
  return !digitalRead(_EN1DIAG1);
}

// Return error status for motor 2
unsigned char DualVNH5019MotorShield::getM2Fault()
{
  return !digitalRead(_EN2DIAG2);
}

Strangely enough in the .cpp file changing:
 
Code:
TCCR3A = 0b10100000;
 TCCR3C = 0b00010001;
 ICR3 = 400;

to

Code:
TCCR3A = 0b10100000;
TCCR3B = 0b00010001;
ICR3 = 400;

gets one motor working but from the research I did TCCR3B should be connected to pin 2 which is not being used.

Many thanks,
MAAhelp



3  Topics / Robotics / Re: Balancing robot for dummies on: April 16, 2012, 06:09:05 am
@Lauszus

Thanks for the detailed post! I will let you know how I get along. Really appreciate it hopefully solves the problem I was encountering smiley
4  Topics / Robotics / Re: Balancing robot for dummies on: April 16, 2012, 04:13:48 am

I got the same problem before I implemented the encoders. Have you any encoders? As I think they make it stay in the same position.

BTW:
I have now ported the code to Arduino.
The code can be found at github: The Arduino version, can now be found at github: https://github.com/TKJElectronics/BalancingRobotArduino

Regards
Lauszus

Thanks for the quick reply and for the code in an arduino version! My main problem is understanding how you are implementing the encoders. Till now I have managed to read the encoder value via interrupts as you have done, what I am not sure is how I am going to use this information to keep the robot in the same position :S

Thanks in advance,
MAAhelp
5  Topics / Robotics / Re: Balancing robot for dummies on: April 15, 2012, 02:38:26 pm
@Lauszus: I saw your robot (on youtube), I would like to congratulate you on the awesome robot. I have also read the thread: Guide to gyro and accelerometer with Arduino including Kalman filtering, although not identical I though it could help me tackle any problems I might encounter. I'm using an Arduino Uno board and a tilt sensor. Although the robot balances well, it drifts (does not stay in a set position). May you elaborate how you managed to make the robot stay in the same position? As I have tried various methods but none of them seem to be working as I intended them to...
FYI: I am balancing the robot with a basic PD controller.

Thanks in advance for the help smiley
6  Topics / Robotics / Re: Balancing robot for dummies on: April 10, 2012, 11:02:50 am
Hi all,

Started a project around 2 months ago to build an autonomous robot. The wheels and motors I'm using are as follows: http://www.technobotsonline.com/banebot-wheel-124x20mm-1-2-hex-shore-50.html, http://www.pololu.com/catalog/product/1443.

Although I am able to balance the robot using a PID algorithm, I am finding it tough to control the position of the robot (via the encoders). I have a tilt sensor sending me the angle the robot is at and setting the motorspeed accordingly. To control the position of the robot I have been varying the reference angle to try and move the robot towards a reference point(eg: x = 0) to keep the robot in the same position but I have not had great results.

State space control would be best to control multiple inputs/outputs but I am not sure how this can be done on the Arduino Uno, any ideas?
If state space isn't used how is the best way to approach the problem I am encountering with the position?

The code I am using is as follows:
Code:

#include "DualVNH5019MotorShield.h"
#include "math.h"

enum PinAssignments {
  encoderPinA = 2,   // right
  encoderPinB = 3,   // left
  clearButton = 12    // another two pins
};


DualVNH5019MotorShield md;
int sensorPin = A2;
float setpointang = 501.0;
int oldangle, oldangle_1, oldangle_2, angle, newangle, current_1, current_2, errorpos, a, b, c = 0;
double sumangle, output, oldpos, oldpos_1, oldpos_2, derivpos, integpos = 0.0;
int Kp = 20;
int ZoneA = 2000;
int ZoneB = 1000;
float motorspeed, deriv, error, errorposctrl;
double Kd = 0.3;   
float freq = 66.67;
float T = ((1/freq)*1000)-0.5;
float Kp_1 = 1.00 ;
float posScaleA = 500.0;
float posScaleB = 1000.0;
float posScaleC = 2000.0;


volatile unsigned int encoderPos = 0;  // a counter for the dial
unsigned int lastReportedPos = 1;   // change management
static boolean rotating=false;      // debounce management

// interrupt service routine vars
boolean A_set = false;             
boolean B_set = false;


void setup()
{
 
  Serial.begin(115200);
  md.init();

  TCCR1B = TCCR1B & 0b11111000 | 0x01;

  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
  pinMode(clearButton, INPUT);
 
  // turn on pullup resistors
  digitalWrite(encoderPinA, HIGH);
  digitalWrite(encoderPinB, HIGH);
  digitalWrite(clearButton, HIGH);

  attachInterrupt(0, doEncoderB, RISING);  //CHANGE
}


void loop()
{

angle = analogRead(sensorPin);

if ((angle < 300) || (angle > 700))
  {
    md.setM1Speed(0);
    md.setM2Speed(0);
  }
else if ((current_1 < 6000) || (current_2 < 6000) )
  {

      //PID
      oldangle_2 = oldangle_1;
      oldangle_1 = oldangle;
      oldangle = newangle;
      newangle = (setpointang - angle);
      deriv = ((newangle + (3*oldangle) -(3*oldangle_1) - oldangle_2)*(freq/6));
     
      error = (Kp*(newangle) + Kd*(deriv));
     
      //Translating PID output value to a value within the range of the motor driver
      motorspeed = ((error/511)*400);

      //Driving the motors
      md.setM1Speed(motorspeed);
      md.setM2Speed(motorspeed);
     
//---------------------------------------------------------------------------------------------------------------------------------------------------------------Angle Control End
//Serial.println(analogRead(A3));   //to plot

  if (lastReportedPos != encoderPos) {   
    if (motorspeed < 0)
    {
      errorpos = errorpos - (lastReportedPos - encoderPos);
    }
    else if (motorspeed > 0)
    {
      errorpos = errorpos + (lastReportedPos - encoderPos);
    }   
    lastReportedPos = encoderPos;
  }



errorposctrl = errorpos;
Serial.print("   errorposctrl:  ");
Serial.print(errorposctrl);

float a = (errorposctrl/posScaleA);
float b = (errorposctrl/posScaleB);
float c = (errorposctrl/posScaleC);


if (abs(errorposctrl) > ZoneA)
{
   setpointang = setpointang - (a);
}
else if (abs(errorposctrl) > ZoneB)
{
   setpointang = setpointang - (b);
}
else
{
   setpointang = setpointang - (c);
}


Serial.print("     a:  ");
Serial.print(a);
Serial.print("    b:   ");
Serial.print(b);
Serial.print("     c:   ");
Serial.println(c);
//






current_1 = (analogRead(A0)) * 34;
current_2 = (analogRead(A1)) * 34;


//Serial.print("    errorpos:   ");
//Serial.print(errorpos);
//Serial.print("     encoderPos:   ");
//Serial.println(encoderPos);

//delay((int)T);

  }
}





//// Interrupt on A changing state
//void doEncoderA(){
//      encoderPos += 1;
//}

// Interrupt on B changing state, same as A above
void doEncoderB()
{
      encoderPos += 1;
}





Thanks in advance,
MAAhelp

It seems that the problem I am currently encountering could be easily solved by just adding the integral term with regards to the PID control I am currently trying. Does this make sense?
7  Topics / Robotics / Re: Balancing robot for dummies on: April 09, 2012, 02:10:45 pm
Hi all,

Started a project around 2 months ago to build an autonomous robot. The wheels and motors I'm using are as follows: http://www.technobotsonline.com/banebot-wheel-124x20mm-1-2-hex-shore-50.html, http://www.pololu.com/catalog/product/1443.

Although I am able to balance the robot using a PID algorithm, I am finding it tough to control the position of the robot (via the encoders). I have a tilt sensor sending me the angle the robot is at and setting the motorspeed accordingly. To control the position of the robot I have been varying the reference angle to try and move the robot towards a reference point(eg: x = 0) to keep the robot in the same position but I have not had great results.

State space control would be best to control multiple inputs/outputs but I am not sure how this can be done on the Arduino Uno, any ideas?
If state space isn't used how is the best way to approach the problem I am encountering with the position?

The code I am using is as follows:
Code:

#include "DualVNH5019MotorShield.h"
#include "math.h"

enum PinAssignments {
  encoderPinA = 2,   // right
  encoderPinB = 3,   // left
  clearButton = 12    // another two pins
};


DualVNH5019MotorShield md;
int sensorPin = A2;
float setpointang = 501.0;
int oldangle, oldangle_1, oldangle_2, angle, newangle, current_1, current_2, errorpos, a, b, c = 0;
double sumangle, output, oldpos, oldpos_1, oldpos_2, derivpos, integpos = 0.0;
int Kp = 20;
int ZoneA = 2000;
int ZoneB = 1000;
float motorspeed, deriv, error, errorposctrl;
double Kd = 0.3;   
float freq = 66.67;
float T = ((1/freq)*1000)-0.5;
float Kp_1 = 1.00 ;
float posScaleA = 500.0;
float posScaleB = 1000.0;
float posScaleC = 2000.0;


volatile unsigned int encoderPos = 0;  // a counter for the dial
unsigned int lastReportedPos = 1;   // change management
static boolean rotating=false;      // debounce management

// interrupt service routine vars
boolean A_set = false;             
boolean B_set = false;


void setup()
{
 
  Serial.begin(115200);
  md.init();

  TCCR1B = TCCR1B & 0b11111000 | 0x01;

  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
  pinMode(clearButton, INPUT);
 
  // turn on pullup resistors
  digitalWrite(encoderPinA, HIGH);
  digitalWrite(encoderPinB, HIGH);
  digitalWrite(clearButton, HIGH);

  attachInterrupt(0, doEncoderB, RISING);  //CHANGE
}


void loop()
{

angle = analogRead(sensorPin);

if ((angle < 300) || (angle > 700))
  {
    md.setM1Speed(0);
    md.setM2Speed(0);
  }
else if ((current_1 < 6000) || (current_2 < 6000) )
  {

      //PID
      oldangle_2 = oldangle_1;
      oldangle_1 = oldangle;
      oldangle = newangle;
      newangle = (setpointang - angle);
      deriv = ((newangle + (3*oldangle) -(3*oldangle_1) - oldangle_2)*(freq/6));
     
      error = (Kp*(newangle) + Kd*(deriv));
     
      //Translating PID output value to a value within the range of the motor driver
      motorspeed = ((error/511)*400);

      //Driving the motors
      md.setM1Speed(motorspeed);
      md.setM2Speed(motorspeed);
     
//---------------------------------------------------------------------------------------------------------------------------------------------------------------Angle Control End
//Serial.println(analogRead(A3));   //to plot

  if (lastReportedPos != encoderPos) {   
    if (motorspeed < 0)
    {
      errorpos = errorpos - (lastReportedPos - encoderPos);
    }
    else if (motorspeed > 0)
    {
      errorpos = errorpos + (lastReportedPos - encoderPos);
    }   
    lastReportedPos = encoderPos;
  }



errorposctrl = errorpos;
Serial.print("   errorposctrl:  ");
Serial.print(errorposctrl);

float a = (errorposctrl/posScaleA);
float b = (errorposctrl/posScaleB);
float c = (errorposctrl/posScaleC);


if (abs(errorposctrl) > ZoneA)
{
   setpointang = setpointang - (a);
}
else if (abs(errorposctrl) > ZoneB)
{
   setpointang = setpointang - (b);
}
else
{
   setpointang = setpointang - (c);
}


Serial.print("     a:  ");
Serial.print(a);
Serial.print("    b:   ");
Serial.print(b);
Serial.print("     c:   ");
Serial.println(c);
//






current_1 = (analogRead(A0)) * 34;
current_2 = (analogRead(A1)) * 34;


//Serial.print("    errorpos:   ");
//Serial.print(errorpos);
//Serial.print("     encoderPos:   ");
//Serial.println(encoderPos);

//delay((int)T);

  }
}





//// Interrupt on A changing state
//void doEncoderA(){
//      encoderPos += 1;
//}

// Interrupt on B changing state, same as A above
void doEncoderB()
{
      encoderPos += 1;
}





Thanks in advance,
MAAhelp
8  Using Arduino / Project Guidance / Re: Arduino Anemometer on: January 04, 2012, 06:22:44 am
Found the problem, the motor encoder had a load/torque ratio that was effecting the output of the LCD. By changing this with a normal clock the problem was solved and everything seems to be working as expected!  smiley Hopefully in practice this will also be the case! Thanks once again for all the help
9  Using Arduino / Project Guidance / Re: Arduino Anemometer on: January 04, 2012, 05:35:09 am
Hey guys,

Thanks for all the help! Solved the problem of getting -1 on the LCD. I noticed that the resolution of the system was not up to standard so I decided to add another binary counter and connecting its outputs to the analog pins of the arduino. All well and good but for some strange reason the value outputted on the encoder is now always 1.5 times the rpm value of the encoder!
Here's the updated code :
Code:
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
int bitstate [8] = {0,0,0,0,0,0,0,0};
int bitaddress[4] = {6, 7, 8, 9};
int abitaddress[4] = {14,15,16,17};
int RSTaddress = 0;
int backLight = 13;    // pin 13 will control the backlight
int pulses = 100; // indicates the number of pulses per revolution
float fixedtime = 31.8; //fixed time interval in ms
int encoderval = 0;
//int encoderval1,encoderval2 =0;
float velocity= 0.00;
void setup()
{
  pinMode (bitaddress[0], INPUT);
  pinMode (bitaddress[1], INPUT);
  pinMode (bitaddress[2], INPUT);
  pinMode (bitaddress[3], INPUT);
  pinMode (abitaddress[0], INPUT);
  pinMode (abitaddress[1], INPUT);
  pinMode (abitaddress[2], INPUT);
  pinMode (abitaddress[3], INPUT);
  pinMode (RSTaddress, OUTPUT);
  pinMode(backLight, OUTPUT);
  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, etc.
  lcd.clear();                  // start with a blank screen
  lcd.setCursor(0,0);           // set cursor to column 0, row 0 (the first row)
  lcd.print("Wind Speed: ");    // change this text to whatever you like. keep it clean.
//  lcd.setCursor(0,1);           // set cursor to column 0, row 1
}

void loop()
{
  digitalWrite (RSTaddress, HIGH);
  delayMicroseconds (100);
  digitalWrite (RSTaddress, LOW);
  delay(fixedtime); //waits for 0.5ms
  bitstate[7]= digitalRead(abitaddress[3]);
  bitstate[6]= digitalRead(abitaddress[2]);
  bitstate[5]= digitalRead(abitaddress[1]);
  bitstate[4]= digitalRead(abitaddress[0]);
  bitstate[3]= digitalRead(bitaddress[3]);
  bitstate[2]= digitalRead(bitaddress[2]);
  bitstate[1]= digitalRead(bitaddress[1]);
  bitstate[0]= digitalRead(bitaddress[0]);
  encoderval = bitstate[0] + (bitstate[1]*2) + (bitstate[2]*4) + (bitstate[3]*8)+(bitstate[4]*16)+(bitstate[5]*32)+(bitstate[6]*64)+(bitstate[7]*128);
//  encoderval1 = PORTD & B11000000;
//  encoderval2 = PORTB & B00000011;
//  encoderval = (encoderval1 >> 6) & (encoderval2 << 2);
  velocity = (encoderval*60000)/(pulses*fixedtime);
  lcd.setCursor (0,1);
  lcd.print (velocity);
  return;
}


Note: in the attached screenshot the rpm was set 1000 and the value outputted was varying from 1548 and 1470. Adding a dc value to Aref had no effect. The same result occurred with no Aref.

Thanks once again for all the help!

10  Using Arduino / Project Guidance / Arduino Anemometer on: January 03, 2012, 05:46:32 pm
Hi all,

I have a problem with a project I am currently doing. I am building an anemometer and have been debugging it via proteus. The schematic is attached to the post. The basic setup is this: there is a rotary encoder which is clocking a counter. The counter bits are being fed to the arduino together with the MR (Master Reset) of the counter. Now the arduino code should do the following:
Set the MR low so that the counter resets.
Every 0.5ms it should read the value of the 4 bits and use the equation found here(http://zone.ni.com/devzone/cda/tut/p/id/3921) to calculate the velocity.
This velocity is displayed on the LCD.
The MR pin is then pulsed so that the counter resets.

The problem is that according to the simulation, the lcd is simply displaying a velocity of -1 and it never changes. I see the counter incrementing and the MR pin being pulsed but the LCD isn't displaying the velocity value. Could someone suggest any possible solutions to the problem?

The code is as follows:
Code:
#include <LiquidCrystal.h>

// Connections:
// rs (LCD pin 4) to Arduino pin 19
// rw (LCD pin 5) to Arduino pin 3
// enable (LCD pin 6) to Arduino pin 4
// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 6, 25, 12, 14
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
int bitstate [4] = {0,0,0,0};
int bitaddress[4] = {6, 7, 8, 9};
int RSTaddress = 0;
int backLight = 13;    // pin 13 will control the backlight
int pulses = 100; // indicates the number of pulses per revolution
int fixedtime = 0.5; //fixed time interval in ms
long encoderval = 0;
//int encoderval1,encoderval2 =0;
long velocity=0;
long time = 0;
void setup()
{
  pinMode (bitaddress[0], INPUT);
  pinMode (bitaddress[1], INPUT);
  pinMode (bitaddress[2], INPUT);
  pinMode (bitaddress[3], INPUT);
  pinMode (RSTaddress, OUTPUT);
  pinMode(backLight, OUTPUT);
  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, etc.
  lcd.clear();                  // start with a blank screen
  lcd.setCursor(0,0);           // set cursor to column 0, row 0 (the first row)
  lcd.print("Wind Speed: ");    // change this text to whatever you like. keep it clean.
  digitalWrite (RSTaddress, HIGH);

 

}

void loop()
{
  encoderval = 0;
  velocity = 0;
  digitalWrite (RSTaddress, LOW);
  delayMicroseconds (fixedtime*1000); //waits for 0.5ms
  bitstate[0]= digitalRead(bitaddress[0]);
  bitstate[1]= digitalRead(bitaddress[1]);
  bitstate[2]= digitalRead(bitaddress[2]);
  bitstate[3]= digitalRead(bitaddress[3]);
  encoderval = bitstate[0] + (bitstate[1]*2) + (bitstate[2]*4) + (bitstate[3]*8);
  //encoderval1 = PORTD & B11000000;
  //encoderval2 = PORTB & B00000011;
  //encoderval = (encoderval1 >> 6) & (encoderval2 << 2);
  time = fixedtime/1000;
  velocity = (encoderval*60)/(pulses*time);
  lcd.setCursor (0,1);
  lcd.print (velocity);
  digitalWrite (RSTaddress, HIGH);
  delay (1);
  return;
}


Thanks in advance for any help!
Pages: [1]