Arduino & SPI - Rotary Position Sensor MLX90316

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!

/* 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);
}
/*
  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
/*
  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);
  

}

Hello,

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

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! :wink:
A +
Francis

Voici la photo =( [![http://[/url]

](Account Suspended "http://[/url]

")](http://www.heberger-image.fr)

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.

/* 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("");
  }
}

Hi there!

I have a problem with this setup. Once I manage to get proper readings, I'll implement it as a very low resistance wind sensor for my sailboat.

Yet, all I read is 0.

My board is MegaADK. SS is 53, SCL is 52 and MOSI is 51.

Any ideas why I am reading only 0s?

Thanks.

Hello, Did you had any success with this chip and the arduino? Would be nice to hear from you

I tried the MLX90316, from the Evaluation Board EVB90316, and received nothing but 0 through the above SPI code. Turns out the module was just sending me an analog output, so the basic analogread worked fine.
Now that I know it is in analog mode, how can I switch the chip to SPI mode (and start using the above code) ?
Many thanks, Peter