Loading...
Pages: [1]   Go Down
Author Topic: Library for HM55B Issue (nesting allowed?)  (Read 931 times)
0 Members and 1 Guest are viewing this topic.
California
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey guys,

I have a problem turning some code from the HM55B tutorial (in the playground) into a library.  For some reason, my library works up to the point where it tries to use a nested function/method (I'm not entirely clear on the differences between methods and functions).

In the CPP code, it stops at after printing "ready for nested method".
Code:
 //HM55B::HM55B_Reset();
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  Serial.println("Ready for nested method");
  ShiftOut(B0000, 3);
  Serial.println("Finished nested method");
  digitalWrite(EN_pin, HIGH);
 
Original working code:
Code:
#include <math.h>  


int CLK_pin = 8;  //clock sync pin
int EN_pin = 9;  //enabler pin
int DIO_pin = 10;  //digital IN OUT pin

int X_Data = 0;
int Y_Data = 0;
int angle;
int ledPin = 2;
int delayVal = 40;

void ShiftOut (int Value, int BitsCount)  {
  for(int i = BitsCount; i >= 0; i--)  {
    digitalWrite(CLK_pin, LOW);
    if ((Value & 1 << i) == ( 1 << i))  {
      digitalWrite(DIO_pin, HIGH);
      //Serial.print("1");
    }
    else {
    digitalWrite(DIO_pin, LOW);
    //Serial.print("0");
  }
  digitalWrite(CLK_pin, HIGH);
  delay(1);
}
//Serial.print(" ");
}

int ShiftIn(int BitsCount)  {
  int ShiftIn_result;
  ShiftIn_result = 0;
  pinMode(DIO_pin, INPUT);
  for (int i = BitsCount; i >= 0; i--)  {
    digitalWrite(CLK_pin, HIGH);
    delay(1);
    if (digitalRead(DIO_pin) == HIGH)  {
      ShiftIn_result = (ShiftIn_result << 1) + 1;
      //Serial.print("X");
    }
    else  {
      ShiftIn_result = (ShiftIn_result << 1) + 0;
      //Serial.print(" ");
    }
    digitalWrite(CLK_pin, LOW);
    delay(1);
  }
  //Serial.print (":");
  
  if ((ShiftIn_result & 1 << 11) == 1 << 11)  {
    ShiftIn_result = (B11111000 << 8) | ShiftIn_result;
  }
  
  return ShiftIn_result;
}

void HM55B_Reset()  {
pinMode(DIO_pin, OUTPUT);
digitalWrite(EN_pin, LOW);
ShiftOut(B0000, 3);
digitalWrite(EN_pin, HIGH);
}

void HM55B_StartMeasurementCommand()  {
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B1000, 3);
  digitalWrite(EN_pin, HIGH);
}

int HM55B_ReadCommand()  {
  int result = 0;
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  ShiftOut(B1100, 3);
  result = ShiftIn(3);
  return result;
}

void setup()  {
  Serial.begin(9600);
  pinMode(EN_pin, OUTPUT);
  pinMode(CLK_pin, OUTPUT);
  pinMode(DIO_pin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  HM55B_Reset();
}

void loop()  {
  getValue();
}

int getValue()  {
    HM55B_StartMeasurementCommand();
  delay(delayVal);
  Serial.println(HM55B_ReadCommand());  //cannot comment out
  Serial.println("************************************");
  //Serial.print(" ");
  X_Data = ShiftIn(11);
  Y_Data = ShiftIn(11);
  //Serial.print(X_Data);
  //Serial.print(" ");
  //Serial.print(Y_Data);
  //Serial.print(" ");
  digitalWrite(EN_pin, HIGH);
  angle = 180 * (atan2(-1 * Y_Data, X_Data) / M_PI);  //angle is atan (-y/x)
  if (angle < 0)  {
    angle = ( 360 + angle );
  }
  else{}
  
  Serial.print("Angle: ");
  Serial.println(angle);
  Serial.println("************************************");
}

Header file:
Code:
/*
 *HM55B.h - Library for using the HM55B compass module
 *Library written by Chris 12/29/2010
 *Released into the public domain.
 *
 *All credit goes to the authors of the code in the previous link
 *All I did was just turn their code into an easy to use library.
 */

#ifndef HM55B_h
#define HM55B_h

#include "WProgram.h"

class HM55B
{
  public:
    int CLK_pin;
    int EN_pin;
    int DIO_pin;  
    HM55B(int CLK_pin, int EN_pin, int DIO_pin);
    int getValue();
  private:
    //int CLK_pin;
    //int EN_pin;
    //int DIO_pin;
    int X_Data;
    int Y_Data;
    int angle;
    void ShiftOut(int Value, int BitsCount);
    int ShiftIn(int BitsCount);
    void HM55B_Reset();
    void HM55B_StartMeasurementCommand();
    int HM55B_ReadCommand();
};

#endif

CPP file:
Code:
/*
 *HM55B.cpp - Library for using the HM55B compass module
 *Use with HM55B.h
 *Library written by Chris 12/29/2010
 *Released into the public domain.
 *
 *All credit goes to the authors of the code in the previous link
 *All I did was just turn their code into an easy to use library.
 */

#include "WProgram.h"
#include "Math.h"
#include "HM55B.h"

HM55B::HM55B(int CLK_pin, int EN_pin, int DIO_pin)
{
  pinMode(CLK_pin, OUTPUT);
  pinMode(EN_pin, OUTPUT);
  pinMode(DIO_pin, INPUT);
  //CLK_pin = clkPin;
  //EN_pin = enPin;
  //DIO_pin = dioPin;
  Serial.begin(9600);
  Serial.println("Library Works");
  
  //HM55B::HM55B_Reset();
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  Serial.println("Ready for nested method");
  ShiftOut(B0000, 3);
  Serial.println("Finished nested method");
  digitalWrite(EN_pin, HIGH);

Serial.println("Compass reset");
}

void HM55B::ShiftOut(int Value, int BitsCount)
{
  for(int i = BitsCount; i >= 0; i--)  {
    digitalWrite(CLK_pin, LOW);
      if ((Value & 1 << i) == ( 1 << i))  {
        digitalWrite(DIO_pin, HIGH);
       }
    else {
    digitalWrite(DIO_pin, LOW);
    }
  digitalWrite(CLK_pin, HIGH);
  delay(1);
  }

}

int HM55B::ShiftIn(int BitsCount)
{
  int ShiftIn_result;
  ShiftIn_result = 0;
  pinMode(DIO_pin, INPUT);
  for (int i = BitsCount; i >= 0; i--)  {
    digitalWrite(CLK_pin, HIGH);
    delay(1);
    if (digitalRead(DIO_pin) == HIGH)  {
      ShiftIn_result = (ShiftIn_result << 1) + 1;
    }
    else  {
      ShiftIn_result = (ShiftIn_result << 1) + 0;
    }
    digitalWrite(CLK_pin, LOW);
    delay(1);
  }
  if ((ShiftIn_result & 1 << 11) == 1 << 11)  {
    ShiftIn_result = (B11111000 << 8) | ShiftIn_result;
  }
  return ShiftIn_result;
}

//void HM55B::HM55B_Reset()
//{
  //pinMode(DIO_pin, OUTPUT);
  //digitalWrite(EN_pin, LOW);
  //HM55B::ShiftOut(B0000, 3);
  //digitalWrite(EN_pin, HIGH);
//}

void HM55B::HM55B_StartMeasurementCommand()
{
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  HM55B::ShiftOut(B1000, 3);
  digitalWrite(EN_pin, HIGH);
}

int HM55B::HM55B_ReadCommand()
{
  int result = 0;
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  HM55B::ShiftOut(B1100, 3);
  result = ShiftIn(3);
  return result;
}

int HM55B::getValue()
{
  HM55B::HM55B_StartMeasurementCommand();
  delay(40);
  Serial.println(HM55B::HM55B_ReadCommand());  //cannot comment out
  X_Data = HM55B::ShiftIn(11);
  Y_Data = HM55B::ShiftIn(11);
  digitalWrite(EN_pin, HIGH);
  angle = 180 * (atan2(-1 * Y_Data, X_Data) / M_PI);  //angle is atan (-y/x)
  if (angle < 0)  {
    angle = ( 360 + angle );
  }
  else{
  }
  return angle;
}

Example Application:
Code:
#include <HM55B.h>

HM55B myCompass = HM55B(8 , 10, 9);
int heading;

void setup()
{
  Serial.begin(9600);
  Serial.println("Initialized");
}

void loop()
{
  heading = myCompass.getValue();
  Serial.println(heading);
  delay(2000);
}

What am I doing wrong?

Thanks in advance for any help.  You guys are awesome on these forums!

-Chris
Logged

If you're interested, check out my open source Qt and Arduino based ROV control software: http://code.google.com/p/rov-suite/

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

Have you worked with libraries before? The comment about not knowing the difference between methods and functions leads me to believe that you are new to C++, too.

In a PC application, you control when the constructors are called. That is not the case on the Arduino. You don't know the order of constructor calls vs. hardware initialization vs. when other constructors are called.

Therefore, calling pinMode() or Serial.begin() or Serial.print(ln)() in a constructor is not a good idea. Has the Serial class been constructed? Has the pin been initialized? You don't know.

Your class needs a begin method, like Serial.begin(), that makes all the calls that your constructor is making.
Logged

California
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I've done a fair amount of playing on the Arduino, but overall I'm new to C/C++.  

So are you saying that I need another begin method other than the normal
Code:
HM55B myCompass = HM55B(24,25,26);
code?

Thanks again for the help!
Logged

If you're interested, check out my open source Qt and Arduino based ROV control software: http://code.google.com/p/rov-suite/

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

Quote
So are you saying that I need another begin method other than the normal
Yes.

Code:
HM55B::HM55B(int CLK_pin, int EN_pin, int DIO_pin)
{
  [glow]pinMode[/glow](CLK_pin, OUTPUT);
  pinMode(EN_pin, OUTPUT);
  pinMode(DIO_pin, INPUT);
  //CLK_pin = clkPin;
  //EN_pin = enPin;
  //DIO_pin = dioPin;
  [glow]Serial.begin[/glow](9600);
  [glow]Serial.println[/glow]("Library Works");

  //HM55B::HM55B_Reset();
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  Serial.println("Ready for nested method");
  ShiftOut(B0000, 3);
  Serial.println("Finished nested method");
  digitalWrite(EN_pin, HIGH);

Serial.println("Compass reset");
}
When is this constructor called? Before the hardware is ready, or after? You don't know, so setting pinMode is not something you want to rely on being performed successfully.

Is it called before or after the Serial instance has been created? You don't know. Yet, use use the Serial instance as though it had already been created.

You call the ShiftOut method, which assumes that the hardware is ready. Is that a valid assumption? You do not know.

The only things that belong in the constructor are the things you have commented out. Everything else belongs in the begin() method, which you call in setup. You know that all the constructors and hardware initialization is complete by then.

Some more questions. What happens if someone else uses your library, and calls Serial.begin() first, with a different baud rate? Your library should not being calling Serial.begin(). The sketch that uses your library should call it.

Why does this code
Code:
void HM55B::HM55B_StartMeasurementCommand()
{
  pinMode(DIO_pin, OUTPUT);
  digitalWrite(EN_pin, LOW);
  [glow]HM55B::[/glow]ShiftOut(B1000, 3);
  digitalWrite(EN_pin, HIGH);
}
use the scope resolution operator on the call to ShiftOut? ShiftOut is not a static method. The scope resolution operator (HM55B:smiley is not needed.
Logged

California
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay.  Thanks for the input!  I'll see if I can get the library working with that information.  I'll also leave the serial code out of the library.  That was mostly in there so I could try to find which line of code wasn't working.  

I didn't know if I had to use that when calling other methods in my library.  

Thanks again!

Chris
Logged

If you're interested, check out my open source Qt and Arduino based ROV control software: http://code.google.com/p/rov-suite/

California
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Paul,

I just finished the library.  Thank you for your help!  

Here's the link:  http://code.google.com/p/rovduino/downloads/list

Thanks again for your help!

Chris
« Last Edit: January 02, 2011, 05:42:45 pm by chriskon149 » Logged

If you're interested, check out my open source Qt and Arduino based ROV control software: http://code.google.com/p/rov-suite/

Pages: [1]   Go Up
Print
 
Jump to: