Go Down

Topic: Arduino & SPI - Rotary Position Sensor MLX90316 (Read 2738 times) previous topic - next topic

noodlesuk

Hi

I'm trying to interface a rotary sensor with my Arduino (PIER MTS-360). I stumbled across this

http://interface.khm.de/index.php/lab/experiments/rotary-positionsensor-mlx90316/

Which uses the MLX90316 sensor.

Although it's based on a different sensor to the one I want to use, from checking the spec sheets, I believe the MTS-360 uses the MLX90316 as it's sensing element. SPI timing and format looks identical:-

A data frame consists of 10 bytes:
• 2 start bytes (AAh followed by FFh)
• 2 data bytes (DATA16 - most significant byte first)
• 2 inverted data bytes (/DATA16 - most significant byte first)
• 4 all-Hi bytes
The Master should send AAh (55h in case of inverting transistor) followed by 9 bytes FFh. The Slave will
answer with two bytes FFh followed by 4 data bytes and 4 bytes FFh.


Has anyone had any success with the Arduino and the MLX90316? I have followed the instructions from the link (see above) and I appear to be getting erroneous data and my limited c + Arduino knowledge is being stretched!

Values in my serial monitor seem to run from 3586 to 3597, instead of the expected 0 to 360. Code is as below, any help would be greatly appreciated!

Code: [Select]
/* MLX90316 Rotary Position Sensor
* KHM 2010 /  Martin Nawrath
* Kunsthochschule fuer Medien Koeln
* Academy of Media Arts Cologne
*/

#include <Metro.h> //Include Metro library
#include <MLX90316.h>


int pinSS = 5;
int pinSCK = 3;
int pinMOSI = 4;
int ii;

Metro mlxMetro = Metro(5);
MLX90316 mlx_1  = MLX90316();

void setup(){

  Serial.begin(115200);
  mlx_1.attach(pinSS,pinSCK, pinMOSI );
  Serial.println(" MLX90316 Rotary Position Sensor");
}

void loop() {
  if (mlxMetro.check() == 1) {
  ii = mlx_1.readAngle();
  Serial.print(ii);
  Serial.println("");
  }
  delay(100);
}



Code: [Select]
/*
  MLX90316.h -  Library to use with Melexis MLX90316 rotary encoder chip.
  Created by Martin Nawrath KHM 2010.
  http://interface.khm.de
  Released into the public domain.
*/

#ifndef MLX90316_h
#define MLX90316_h



class MLX90316
{
  public:
// constructor
    MLX90316();
// attach
void attach(int pin1, int pin2, int pin3);
      // read sensor angle value

int readAngle();

   //  private:
   
int _pinSCK;
int _pinSS;
int _pinMOSI;
uint8_t  _spiByte(uint8_t  tx);

};


#endif


Code: [Select]
/*
  MLX90316.cpp -  Library to use with Melexis MLX90316 rotary encoder chip.
  Created by Martin Nawrath KHM 2010.
  http://interface.khm.de
  Released into the public domain.
*/

#include "Arduino.h"
#include "MLX90316.h"


// constructor
MLX90316::MLX90316(){


};
// attach
void MLX90316::attach(int pinSS, int pinSCK, int pinMOSI )
{
_pinSS = pinSS;
_pinSCK = pinSCK;
_pinMOSI = pinMOSI;

pinMode(_pinSS , OUTPUT);
pinMode(_pinSCK , OUTPUT);
pinMode(_pinMOSI , OUTPUT);
}

//******************************************************
int MLX90316::readAngle() {
  byte bb;
  int ret=-1;
  unsigned int rr;
  long int lo;

  digitalWrite(_pinSS,0);


  bb=_spiByte(0x55);  // send sync byte ( AA reversed order = 55?)
  bb=_spiByte(0xFF);  // send sync byte FF)
 
   bb=_spiByte(0xFF); // receive 1. byte of mlx msb data
   rr= (bb << 8);   
   bb=_spiByte(0xFF); // receive 2. byte of lsb mlx data
   rr=rr+bb;
   
  if ((rr & 3) == 2) {
   
    if ( rr & (1 << 4)) ret=-2;  // signal to strong
    if ( rr & (1 << 5)) ret=-3;  // signal to weak
}
   
  if ((rr & 3) == 1) { // valid angle data ?
     rr = (rr >> 2);
     lo= rr ;
     lo=lo *  3600 / 16384; // scale output to 360 deg, untit in tens of deg.
    ret= lo;
  }

  digitalWrite(_pinSS,1);
  return(ret);


}

//*************************************************************
// send and receive SPI byte  to/from MLX90316 Chip
uint8_t  MLX90316::_spiByte(uint8_t  tx) {
  byte rxb=0;

  for (int ix = 0; ix < 8; ix++){  // receive/transmit 8 SPI bits

    digitalWrite(_pinSCK,1);    // clocksignal positive slope
    rxb = ( rxb << 1);           // shift received byte left

    pinMode(_pinMOSI,INPUT);    // switch MOSI pin to input
    digitalWrite(_pinMOSI,1);   // turn port internal pullup resistor on

    if (digitalRead(_pinMOSI) ==1) rxb = rxb | 1; // read respose bit from sensor
    digitalWrite(_pinMOSI,0);   // turn port internal pullup resistor off
    pinMode(_pinMOSI,OUTPUT);   // switch MOSI pin to output

    // write SPI transmit bit to sensor
    if ((tx & 1) != 0) digitalWrite(_pinMOSI,1);
    else digitalWrite(_pinMOSI,0);
    tx= ( tx >> 1);

    digitalWrite(_pinSCK,0);   // clocksignal negative slope
    digitalWrite(_pinMOSI,0);  // set MOSI databit 0
  }
 
  return(rxb);
 

}

du438

Hello,

Reading the graduations of indexing tables are not obvious.
As everyone's vision of loan decreases with age! :smiley-eek:

Here is a new project in the electronic display degree of angular displacement of a rotary table.
ARDUINO module to display on an LCD the angular value of the rotational movement of a small magnet placed over a specific sensor.

The sensor is mini, it is placed on the board orange. For now it works well.
I have yet to find a magnet Ø6mm to manufacture the rotary support final assembly.
The PCB is under construction, including supporting the Arduino mini LCD, sensor and filtered power of 5 volts.

  I think to finish the project in September.
I have a good display in degree trick requires the proper magnet ...
The model has many son but I am confused! ;)
A +
  Francis


bheintz

noodlesuk,

I changed the pin settings from Martin Narwrath's sketch due to the expected SPI connections on the different boards, see the Arduino SPI Library http://arduino.cc/en/Reference/SPI.

int pin_SS = 10;  // White Wire
int pinSCLK = 13; // Violet Wire
int pinMOSI = 11; // Grey Wire

In the MLX90316.cpp library ii is assigned different default values in case of a problem:
     * if ii = -1 then no SPI signal
     * if ii = -2 then signal too strong
     * if ii = -3 then signal too weak

The output is actually expected to be 0-3600, ten times the actual angle.

the following is Martin Narwrath's sketch with a few minor changes and notations.
Code: [Select]
/* MLX90316 Rotary Position Sensor
* KHM 2010 /  Martin Nawrath
* Kunsthochschule fuer Medien Koeln
* Academy of Media Arts Cologne

* MLX90316KDC-BDG-100-RE Rotary Position Sensor
* K=Temperature Range -40ºC to 125ºC
* DC = SOIC150
* BDG = SPI Version
* 100 = SPI
* RE = Reel

* pin 1 = Vdd - 5vdc (Red Wire)
* pin 2 = Ground (Black Wire)
* pin 3 = _SS, is a 5v tolerant digital input
* pin 4 = SCLK, is a 5v tolerant digital input
* pin 5 = MOSI, is a 5v tolerant digital input/output
* pin 6 = Ground
* pin 7 = Vdig
* pin 8 = Ground
* note: pin 1 and pin 7 connect with Ground with capacitor.

* MOSI (Master Out Slave In) the master sends a commant to the slave to get the angle out.
* MLX90316.cpp sets _SS, SCLK, and MOSI to OUTPUT in beginning, sets MOSI to INPUT at the end.
* readAngle is 10 x angle, thus 3600 is 360.0º
*/



// in this sketch the sensor does not communicates using the "SPI.h library"
#include "Metro.h"     //Include Metro library
#include "MLX90316.h"  // Include MLX90316 library

int pin_SS = 10;  // White Wire
int pinSCLK = 13; // Violet Wire
int pinMOSI = 11; // Grey Wire
int ii;
int angle;
Metro mlxMetro = Metro(5);
MLX90316 mlx_1  = MLX90316();
void setup(){
  Serial.begin(115200); //Initializes the SPI bus by setting SCK, MOSI, and SS to outputs, pulling SCK and MOSI low, and SS high.
  mlx_1.attach(pin_SS,pinSCLK, pinMOSI );
  Serial.println(" MLX90316 Rotary Position Sensor");
}

void loop() {
  if (mlxMetro.check() == 1) {
    ii = mlx_1.readAngle();
    angle = ii/10; //readAngle gives 10 * degrees, thus 3600 = is 360.0º
    /* if ii = -1 then no SPI signal
     * if ii = -2 then signal too strong
     * if ii = -3 then signal too weak
     * "angle" will read 0 if signal is lost
    */   
    Serial.print(angle);
    Serial.println("");
  }
}

Go Up