Go Down

Topic: Arduino & SPI - Rotary Position Sensor MLX90316 (Read 3553 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("");
  }
}

ErcinUral

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.


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy