V2XE with arduino

I have been working on the V2XE for quite a few days now i cannot seem to get it work… I am trying to interface to the Arduino UNO board via SPI. I have pulled down the the sync, chip-select, clock and MOSI pin. All i get are zeros in response… :confused:

the following is my code:

#include<SPI.h>

int x=0;

byte sync_flag=0xAA;

byte module_info=0x01;

byte terminator_flag=0x00;

void setup()

{

SPI.setBitOrder(MSBFIRST);

SPI.setDataMode( SPI_MODE0);

SPI.setClockDivider( SPI_CLOCK_DIV8);

Serial.begin(9600); // start the SPI library:

Serial.println(" ");

Serial.println(“Start communication with V2XE”);

while (!Serial.available());

Serial.read();

SPI.begin(); // initalize the data ready and chip select pins:

pinMode(7, OUTPUT); //sync pin

pinMode(10, OUTPUT);//chipselect

digitalWrite(10,HIGH);

}

void loop()

{

digitalWrite(10,LOW);

//starting sync

digitalWrite(7,LOW);

delayMicroseconds(100);//giving time to sync

digitalWrite(7,HIGH);

delayMicroseconds(100);//giving time to sync

digitalWrite(7,LOW);

delay(20);//giving time to sync

//sync complete

//Sending start signals

SPI.transfer(sync_flag);// sync flag

// delayMicroseconds(100);//

SPI.transfer(module_info);//Frame Type

SPI.transfer(terminator_flag);

digitalWrite(10,HIGH);

delayMicroseconds(50);

digitalWrite(10,LOW);

SPI.transfer(sync_flag);// sync flag

SPI.transfer(0x02);//Frame Type

for(int i=0; i<10;i++)

{

x= SPI.transfer(terminator_flag);

}

digitalWrite(10,HIGH);

Serial.println(“Module type”);

Serial.println(x,BIN);

Serial.println(" ");

}

Hi Ahmed

I have a project using a V2Xe. I have found that you need to keep repeating the SPI.transfer (I will try and use your terms but I may have misunderstood) using 0 data until the sync byte appears. Once you see the sync then start clocking in the rest of the data

Sending the sync flag again will confuse it.

Also you have to delay between SPI.transfers for both read and write – I notice you have a delay commented out during the transmit.

So something like this for the receive

sync = 0 ;

while( sync != SYNC ){

sync = SPI.transfer(0);

delayMicroseconds(50);

};

frametype= SPI.transfer(0);

delayMicroseconds(50);

Graham

Hey Graham,

Thanks alot for the reply I will try it out and let you know if it works…

This is my schematic and this is my code … I still cant get it to work … If you could give me your code ill be greatful…

#include<SPI.h>

byte sync_flag=0xAA;

byte module_info=0x01;

byte terminator_flag=0x00;

int x=0;

int SYNC_PIN=8;

long frametype=0;

void setup()

{

// SPI.setBitOrder(MSBFIRST);

SPI.setDataMode( SPI_MODE0);

//SPI.setClockDivider( SPI_CLOCK_DIV8);//Since max SCLK frequency 3.6864 MHz

Serial.begin(9600); // start the SPI library:

Serial.println(" ");

Serial.println(“Start communication with V2XE”);

SPI.begin(); // initalize the data ready and chip select pins:

pinMode(SYNC_PIN, OUTPUT); //sync pin

pinMode(10, OUTPUT);//chipselect

delay(20);

Serial.println(“Syncing V2XE…”);

v2xe_sync();//syncing V2XE

Serial.println(“Syncing V2XE DONE…”);

}

void loop()

{

//Sending start signals

digitalWrite(10,LOW);

Serial.println(“CS LOW”);

SPI.transfer(sync_flag);// sync flag

Serial.println(“sync flag sent”);

delayMicroseconds(50);

SPI.transfer(module_info);//Frame Type

delayMicroseconds(50);

Serial.println(“module info request”);

SPI.transfer(terminator_flag);

Serial.println(“terminator flag”);

while(x!= 0xAA)

{

delayMicroseconds(50);

x = SPI.transfer(0);

}

Serial.println("sync response = ");

Serial.println(x,HEX);

Serial.println(" ");

frametype= SPI.transfer(0);

delayMicroseconds(50);

digitalWrite(10,HIGH);

Serial.println("V2XE response = ");

Serial.println( frametype,HEX);

Serial.println(" ");

/* //Sending start signals

digitalWrite(10,LOW);

SPI.transfer(sync_flag);// sync flag

SPI.transfer(0x02);//Frame Type

SPI.transfer(terminator_flag);

for(int i=0; i<2;i++)

{

x= SPI.transfer(terminator_flag);

}

Serial.println(x);

Serial.println(" ");

*/

}

void v2xe_sync()

{

digitalWrite(SYNC_PIN, LOW);

delayMicroseconds(100);

digitalWrite(SYNC_PIN, HIGH);

delayMicroseconds(100);

digitalWrite(SYNC_PIN, LOW);

delay(20);

}

The program gets stuck in the while loop as the V2XE does not send the sync signal

Salam Ahmad

i was looking for arduino code of V2xe have you got one that is working?

I haven’t got any Arduino code, mine runs on Windows and Linux using a USB to SPI converter so has additional complexity.

This is it stripped down, command is the command string, clength is the command length in bytes, response is a buffer for the response and rlength is the expected response length in bytes.

Sleeps are in milliseconds

int SPI_VX2e_Command( BYTE command , int clength , BYTE response, int rlength ){

int i ;

for( i = 0 ; i < clength ; i++ ){

WriteByte( command );

  • Sleep( 10 );*
  • }*
  • for( i = 0 ; i < clength ; i++ ){*
    _ response = ReadByte();_
    * }*
    * Sleep(10);*
    * if( rlength == 0 )*
    * {*
    * return true ;*
    * }*
    * // Look for sync (0xAA)*
    * for( i = 0 ; i < 500 ; i++ ){*
    * WriteByte( 0 );*
    * response[0] = ReadByte();*
    * if( response[0] == SYNC )*
    * break ;*
    * Sleep(10);*
    * }*
    * for( i = 1 ; i < rlength ; i++ ){*
    * WriteByte( 0 );*
    _ response = ReadByte();
    * }
    debug( “Command %d %s \n”,
    command[1] ,
    response[0] == SYNC ? “ack” : “nack” );
    return (response[0] == SYNC );
    }*
    You really need to check that the signals look right.
    On the circuit diagram it looks like the GND pin is connected to the SYNC pin which is being pulled high. This is wrong but it may be the way the drawing has been done.
    _

I have had some further thoughts on this.

I think the code should be modified in this way. If the command doesn’t work time it out, using a count for example, and then retry it. If after several attempts that doesn’t work reset it using the sync signal and try again. This assumes that the GND and SYNC are not tied together. I find the device does need resetting after power up.

The code at the end which seems to transmit frame type 2 should be removed. It won’t work!

Note that my interface is buffered due to the USB-SPI converter so I can write data and then read what was sent later. You can’t and don’t need to do this.

Hi,

I write the code that works only I can’t display the float values correctly. When I change the float in int I see results.

Maybe can somebody help me with this.

I have used a logic level converter. I don’t know if it is working when you connect the V2Xe directly to the Arduino Uno board.

Otherwise you can use resistors I have seen somewhere.

Good luck.

#include “SPI.h”

#include “pins_arduino.h”

// used pins

//#define SS 10 // SPI “slave select” pin. active low. (same as the analog pin 0, used in digital)

#define SCK_PIN 13

#define MISO_PIN 12

#define MOSI_PIN 11

#define SYNC_PIN 7 // Sync resets the compass’ communication buffers on raising front

#define kSyncChar 0xAA

#define kTerminator 0x00

char a[8];

enum{

// commands/frame types

kGetModInfo = 1, // 0x01

kModInfoResp, // 0x02

kSetDataComponents, // 0x03

kGetData, // 0x04

kDataResp, // 0x05

kSetConfig, // 0x06

kGetConfig, // 0x07

kConfigResp, // 0x08

kSaveConfig, // 0x09

kStartCal, // 0x0A

kStopCal, // 0x0B

kGetCalData, // 0x0C

kCalDataResp, // 0x0D

kSetCalData, // 0x0E

// data types

kRawX = 1, // 0x01

kRawY, // 0x02

kCalibratedX, // 0x03

kCalibratedY, // 0x04

kHeading, // 0x05

kMagnitude, // 0x06

kTemperature, // 0x07

kDistortion, // 0x08

kCalStatus, // 0x09

// config types

kDeclination = 1, // 0x01

kTrueNorth, // 0x02

kCalSampleFreq, // 0x03

kSampleFreq, // 0x04

kPeriod, // 0x05

kBigEndian, // 0x06

kDampingSize, // 0x07

// cal data types

kXOffset = 1, // 0x01

kYOffset, // 0x02

kXGain, // 0x03

kYGain, // 0x04

kPhi, // 0x05

kCalMagnitude // 0x06

};

typedef struct

{

int x,y;

float xe, ye;

float heading;

float magnitude;

float temperature;

byte distortion, calstatus;

} V2XEData;

V2XEData* data;

void setup (void)

{

Serial.begin (115200);

Serial.println ();

SPI.begin ();

pinMode(SCK_PIN, OUTPUT);

pinMode(MOSI_PIN, OUTPUT);

pinMode(MISO_PIN, INPUT);

pinMode(SYNC_PIN, OUTPUT);

digitalWrite(SYNC_PIN, LOW);

// Put SCK, MOSI, SS pins into output mode

// also put SCK, MOSI into LOW state, and SS into HIGH state.

// Then put SPI hardware into Master mode and turn SPI on

// Slow down the master a bit

SPI.setClockDivider(SPI_CLOCK_DIV128);

delay(20);

// sync the compass

v2xe_sync();

} // end of setup

void v2xe_sync(){

digitalWrite(SYNC_PIN, LOW);

delayMicroseconds(100);

digitalWrite(SYNC_PIN, HIGH);

delayMicroseconds(100);

digitalWrite(SYNC_PIN, LOW);

delay(20);

}

byte spi_transmit (const byte what) {

byte a = SPI.transfer (what);

return a;

}

byte spi_receive_byte () {

return spi_transmit(0);

}

void ask_mod_info(){

byte index, count, buffer[64];

index = 0;

// transmit the command

buffer[index++] = kSyncChar; // all frames always start with a sync character

buffer[index++] = kGetModInfo; // the frame type

buffer[index++] = kTerminator; // don’t forget the terminator

// now transmit the command

count = index;

index = 0;

while (count–) {

// just throw away whatever is receive

spi_transmit(buffer[index++]);

}

}

bool spi_receive_info() {

byte frame;

bool found = false;

while (spi_receive_byte() != kSyncChar) delayMicroseconds(250);

frame = spi_receive_byte();

// the next byte will be the response info type

if (frame == kModInfoResp) {

// the next 8 bytes will be the module type and firmware version

for (int i = 0; i< 8; i++){

a = spi_receive_byte();
found = true;
}
}
return found;
}
void ask_heading() {
byte index, count, buffer[64];
index = 0;
// transmit the command
buffer[index++] = kSyncChar; // all frames always start with a sync character
buffer[index++] = kSetDataComponents; // the frame type
buffer[index++] = 9; // number of components to retrieve
buffer[index++] = kRawX; // x
buffer[index++] = kRawY; // y
buffer[index++] = kCalibratedX; // xe
buffer[index++] = kCalibratedY; // ye
buffer[index++] = kHeading; // heading
buffer[index++] = kMagnitude; // magnitude
buffer[index++] = kTemperature; // temperature
buffer[index++] = kDistortion; // distortion
buffer[index++] = kCalStatus; // calstatus
buffer[index++] = kTerminator; // don’t forget the terminator
// now transmit the command
count = index;
index = 0;
//Serial.println(“Ask heading”);
while (count–) {
// just throw away whatever is receive
spi_transmit(buffer[index++]);
}
}
void get_data() {
byte index, count, buffer[64];
index = 0;
// transmit the command
buffer[index++] = kSyncChar; // all frames always start with a sync character
buffer[index++] = kGetData; // the frame type
buffer[index++] = kTerminator; // don’t forget the terminator
// now transmit the command
count = index;
index = 0;
//Serial.println(“Get data”);
while (count–) {
// just throw away whatever is receive
spi_transmit(buffer[index++]);
}
}
bool receive_data() {
byte frame, count, type;
bool found = false;
//Serial.println(“Wait for Sync”);
while (spi_receive_byte() != kSyncChar) delayMicroseconds(250);
frame = spi_receive_byte();
//Serial.println(frame);
// the next byte will be the response frame type
if (frame == kDataResp) {
// the next byte will be the data component count
count = spi_receive_byte();
//Serial.println(count);
while (count–) {
// get the component data identifier
type = spi_receive_byte();

//Serial.println(type);
switch(type) {
case kRawX:
//Serial.println(spi_receive_byte());
data->x = int(spi_receive_byte());
found = true;
break;
case kRawY:
//Serial.println(spi_receive_byte());
data->y = int(spi_receive_byte());
found = true;
break;
case kCalibratedX:
//Serial.println(spi_receive_byte());
data->xe = float(spi_receive_byte());
found = true;
break;
case kCalibratedY:
//Serial.println(spi_receive_byte());
data->ye = float(spi_receive_byte());
found = true;
break;
case kHeading:
//Serial.println(spi_receive_byte());
data->heading = float(spi_receive_byte());
found = true;
break;
case kMagnitude:
//Serial.println(spi_receive_byte());
data->magnitude = float(spi_receive_byte());
found = true;
break;
case kTemperature:
//Serial.println(spi_receive_byte());
data->temperature = float(spi_receive_byte());
found = true;
break;
case kDistortion:
//Serial.println(spi_receive_byte());
data->distortion = spi_receive_byte();
found = true;
break;
case kCalStatus:
//Serial.println(spi_receive_byte());
data->calstatus = spi_receive_byte();
found = true;
break;
default:
// error condition
break;
}
}
// cleanup of the eventual garbage
while (spi_receive_byte() != kTerminator);
}
return found;
}
void loop (void)
{
ask_mod_info();
delay(10);
if (spi_receive_info()) {
Serial.print ("Module Type: ");
Serial.print (a[0]);
Serial.print (a[1]);
Serial.print (a[2]);
Serial.println (a[3]);
Serial.print ("Firmware Version: ");
Serial.print (a[4]);
Serial.print (a[5]);
Serial.print (a[6]);
Serial.println (a[7]);
}
delay(500);
ask_heading();
delay(10);
get_data();
if (receive_data()) {
Serial.print ("Heading : ");
Serial.println ((data->heading));
Serial.print ("Magnitude : ");
Serial.println ((data->magnitude));
Serial.print ("XRaw : ");
Serial.println ((data->x));
Serial.print ("YRaw : ");
Serial.println ((data->y));
Serial.print ("XCal : ");
Serial.println ((data->xe));
Serial.print ("YCal : ");
Serial.println ((data->ye));
Serial.print ("Temperature : ");
Serial.println ((data->temperature));
Serial.print ("Distortion : ");
Serial.println ((data->distortion));
Serial.print ("CalStatus : ");
Serial.println ((data->calstatus));
}
delay(500);
} // end of loop

I think statements like this are wrong as you are only receiving one byte

data->magnitude = float(spi_receive_byte())

you have to receive 4 bytes for float and int values

e.g.

char data = (char) &(data->magnitude);

data[0] = spi_receive_byte() ;

data[1] = spi_receive_byte() ;

data[2] = spi_receive_byte() ;

data[3] = spi_receive_byte() ;

Make sure endianess is set up correctly.