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