Go Down

Topic: Hmc6352 (Electronic compass) sent over Xbees (Read 22534 times) previous topic - next topic

AUS_matt

Ihave a school project to complete, and part of the system requires me to send a heading over wireless.

I am using a a pro mini and trying to send the the hmc6352 heading  over serial through  xbees to a Mega, with not much success.  

I get a lot of gibberish, but through alot of searching i think it has something to do with only sending bits, and i need to send it in strings or packets or something like that, ( because the the value is between 0-359, (360 Degrees))

i havent done much coding that consist with xbees, or even serial communication, only sending Data back to a PC for debugging. The xbees are configured.

Coding is still a new language to me and any information on sending packets or strings or anything else that can help me send information over the Xbees or even over wired serial would help. And a big ask to please explain in detail about the stuff.



My transmitter code without the Hmc6352 stuff

int reading = 0;

void setup() {
Serial.begin(9600);             //for xbees

void loop(){
.......                                    // HMC6352 stuff goes here

Serial.println(Heading);      // print the heading  through xbees
delay(50)
}



Receiving code on Mega
- i really didn't know what to do

int heading;
void setup() {
Serial1.begin(9600);           // Serial port enable from Xbee
Serial.begin(9600);             // serial port for PC
}

void loop() {
If (Serial1.available()) {       // if there is bytes available coming from the xbee
heading = Serial1.read();    // read it
Serial.println(heading) ;      //send it to the PC to see the heading. Eventually it will be on an lcd sceen
delay (50);
}

Any help will be great and sample code would be Awesome.
Thanks

PaulS

The optional 2nd argument DEC causes the Serial.print (pr println) command to output the value as a string representation of the 1st value, which is the default behavior if no 2nd argument is specified.

Your problem is that you are printing an integer, which can have a range of values from -32768 to 32767. This means that as few as one character to as many as 6 characters are required to contain the string representation of the value. Add the carriage return/line feed added by the println command, and you would need to receive up to 8 ascii values.

You are, instead, receiving 1, and treating it as an integer, when, in reality, it is an ascii representation of the value.

You should change your sender code to add a specific start of packet marker, the packet, and an end of packet marker:
Code: [Select]
Serial.print("<");
Serial.print(heading);
Serial.print(">");


Then, change the receiver to read the whole packet:
Code: [Select]
char inData[10];
int index;
boolean started = false;
boolean ended = false;

void loop()
{
  while(Serial.available() > 0)
  {
      char aChar = Serial.read();
      if(aChar == '>')
      {
          started = true;
          index = 0;
          inData[index] = '\0';
      }
      else if(aChar == '>')
      {
          ended = true;
      }
      else if(started)
      {
          inData[index] = aChar;
          index++;
          inData[index] = '\0';
      }
  }

  if(started && ended)
  {
      // Convert the string to an integer
      int inInt = atoi(inData);

      // Use the value

      // Get ready for the next time
      started = false;
      ended = false;

      index = 0;
      inData[index] = '\0';
  }
}


This code will read any data on the serial port, discarding anything until it sees a start of packet marker. It marks that the packet has started and initializes the array of characters to hold the packet.

It continues reading until it sees the end of packet marker. It adds each character to the end of the array, advances the index into the array, and adds a NULL. This is needed to keep the array NULL terminated, which atoi needs.

Only when the start of packet and end of packet markers have both been received does it make any attempt to use the data.

Before the data can be used, the string needs to be converted to an integer, which is what atoi does.

After the data has been used, the array is initialized, and the flags are reset.

AUS_matt

Thanks PaulS, Your truly Awesome  :).

Just a Quick Question, are there any limits, and can i send multiple bits of code this way like  a statement like "peter piper picked a pack of pickled peppers .." ect, if i wanted to? or how would i do it for 4 different 10 bit analogue readings ( just set up one after the other )?


For anyone else, looking at the code, in PaulS code the   > i is around the wrong way it should be <.
" if(aChar == '>') " it should be,  if(aChar == '<')

this is the code im using for the receiving arduino Mega
Code: [Select]
char inData[10];
int index;
boolean started = false;
boolean ended = false;
void setup(){
Serial1.begin(9600);
Serial.begin(9600);
}
void loop()
{
  while(Serial1.available() > 0)
  {
      char aChar = Serial1.read();
      if(aChar == '<')
      {
          started = true;
          index = 0;
          inData[index] = '\0';
      }
      else if(aChar == '>')
      {
          ended = true;
      }
      else if(started)
      {
          inData[index] = aChar;
          index++;
          inData[index] = '\0';
         }
  }
 

  if(started && ended)
  {
      // Convert the string to an integer
      int inInt = atoi(inData);
         Serial.println(inInt);
      // Use the value

      // Get ready for the next time
      started = false;
      ended = false;

      index = 0;
      inData[index] = '\0';
 
}
}


for a normal arduino, just change change all the  "Serial1" to "Serial" and take a "Serial1.begin(9600);" out of the void setup.

PaulS

Quote
For anyone else, looking at the code, in PaulS code the   > i is around the wrong way it should be <.
" if(aChar == '>') " it should be,  if(aChar == '<')


Oops. Glad you figured that out.

Quote
are there any limits

The serial buffer is 128 bytes long, although there are problems when it actually holds more than 127 bytes.

Quote
can i send multiple bits of code this way like  a statement like "peter piper picked a pack of pickled peppers .."


If that means something to your Arduino sketch, by all means you can send it. Even if it doesn't, you can send it.

Quote
or how would i do it for 4 different 10 bit analogue readings ( just set up one after the other )


Some separator between the readings would be needed, such as a space.

<1023 512 90 43>

Then, use the strtok function to extract the tokens based in the separator (the space). Convert each token to an integer.

AUS_matt

thanks again :).

Just another question, Im controlling a stepper motor by a Easy driver stepper motor controller and when i Serial.print some data it messes up the timing of the stepper motor (because im controlling the speed through each loop).     It works fine without the serial print.
Is there any way to get around this problem, because i need the stepper motor to receive my potentiometer reading from the other arduino ( via the xbees )
heres my code with the Serial print
the serial print in this code isn't anything specieal, i have just got it there to see what it will do and in this case alter the timing  of the stepper motor
 
Code: [Select]
int potpin = 0;                      //joystick
int potval;                          //Joystick value
int dirPin = 2;                      //direction pin on stepper motor driver
int stepperPin = 3;                  //stepper pin on stepper motor driver
boolean dir;                         // sets it to ither true or false(forward, reverse)                
long waitTime;                       // time beteween each step( in microseconds)

void setup() {
 Serial.begin(9600);                
 pinMode(potpin, INPUT);            
 pinMode(dirPin, OUTPUT);
 pinMode(stepperPin, OUTPUT);
}

void loop(){
potval = analogRead(potpin);        
 if (potval >= 510){                     //if value greater than middle of joystick
  waitTime = potval;
  waitTime = map (waitTime,510,1024,2000,90); //map value from joystick to suit stepper motor wait time
  digitalWrite (dirPin,true);
  digitalWrite(stepperPin, HIGH);
  delayMicroseconds(waitTime);
  digitalWrite(stepperPin, LOW);
  delayMicroseconds(waitTime);
  Serial.println(waitTime);          // the serial print isnt anything specieal i have just got it there to
                                     // see what it will do and in this case alter the timing og the stepper motor
}
else if (potval <=500){              // if value less than middle of joystick    
  waitTime = potval ;
  waitTime = map (waitTime,0,500,90,2000);  // map value from joystick to suit stepper motor wait time
  digitalWrite (dirPin,false);
  digitalWrite(stepperPin, HIGH);
  delayMicroseconds(waitTime);
  digitalWrite(stepperPin, LOW);
  delayMicroseconds(waitTime);
  Serial.println(waitTime);
}
}
 

PaulS

Because the Serial.println is not instantaneous, you would need to measure how long each Serial.println took, and subtract that value from the 2nd delayMicroseconds time in each block.

Or, you could print the value first, then move the stepper motor.

In general, doing serial communication in the middle of time-critical blocks of code is not a good idea.

However, since your timing is based on the position of a joystick, it's hard to imagine that timing is really critical.

AUS_matt

thanks, also increasing the bit rate helped, what is the highest arduino can send?

PaulS

Quote
increasing the bit rate helped, what is the highest arduino can send?


115200

AUS_matt

hi, again :)

I set up my xbees up, one as a znet  2.5 coordintator AT and one as a znet 2.5 router/end device AT

I got them talking (thanks to your code) but a soon a i swapped the xbees around, (the roles swapped) i got the transmitted data randomly, not consistently like before. This is a problem because i need to sent and receive data from both xbees

PaulS

The series 2/2.5 models are not really designed to be used as point to point radios (i.e bi-directional communication between just 2 devices). That is what the series 1 radios are designed for.

I was never able to get two series 2 radios to talk to each other. I got one to send and the other to receive, but I wasn't able to get a response back.

Perhaps someone else has figured out how.

Go Up