{"id":109,"date":"2010-04-07T18:45:13","date_gmt":"2010-04-07T16:45:13","guid":{"rendered":"http:\/\/www.anyma.ch\/blogs\/research\/?p=109"},"modified":"2010-04-07T19:22:05","modified_gmt":"2010-04-07T17:22:05","slug":"very-nice-sensor-mlx90316-rotary-position-sensor","status":"publish","type":"post","link":"http:\/\/www.anyma.ch\/blogs\/research\/2010\/04\/07\/very-nice-sensor-mlx90316-rotary-position-sensor\/","title":{"rendered":"Very nice sensor: MLX90316  Rotary Position Sensor"},"content":{"rendered":"<p>Today we&#8217;ve played around with a new sensor. The <a href=\"http:\/\/www.melexis.com\/Sensor_ICs_Hall_effect\/Triaxis_Hall_ICs\/MLX90316_566.aspx\">Melexis MLX90316<\/a> can detect the angular position of a magnet. From it&#8217;s <a href=\"http:\/\/www.melexis.com\/Assets\/MLX90316_DataSheet_4834.aspx\">datasheet<\/a>:<\/p>\n<blockquote><p>In combination with the appropriate signal processing, the magnetic flux density of a small magnet (diametral magnetization) rotating above the IC can be measured in a non-contacting way (Figure 3). The angular information is computed from both vectorial components of the flux density (i.e. BX and BY). MLX90316 produces an output signal proportional to the decoded angle. The output is selectable between Analog, PWM and Serial Protocol.<\/p>\n<p><a href=\"http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-110\" title=\"Typical Application\" src=\"http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-3.png\" alt=\"\" width=\"353\" height=\"278\" srcset=\"http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-3.png 353w, http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-3-300x236.png 300w\" sizes=\"(max-width: 353px) 100vw, 353px\" \/><\/a><\/p><\/blockquote>\n<p>We&#8217;ve ordered the SPI version from <a href=\"https:\/\/www.distrelec.ch\/ishopWebFront\/catalog\/product.do\/para\/artView\/is\/true\/and\/node\/is\/37846\/and\/productNr\/is\/647248\/and\/id\/is\/01\/and\/series\/is\/1.html\">distrelec<\/a> and after having some first troubles to talk to it, I&#8217;m really impressed.<\/p>\n<p><strong>Noise free 360\u00b0 rotational data<\/strong> with <strong>14 bit precision<\/strong>!!<\/p>\n<p>Really cool, this will help a lot to improve reliability of my<a href=\"http:\/\/www.anyma.ch\/2005\/research\/3d-joystick\/\"> 3D Joystick<\/a>, for example&#8230;.<\/p>\n<h2>Caveats<\/h2>\n<p>The\u00a0 MLX90316 uses only one line for MOSI\/MISO, and in the datasheet the tell us to do something like this:<\/p>\n<blockquote><p><a href=\"http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-112\" title=\"Picture 4\" src=\"http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-4.png\" alt=\"\" width=\"512\" height=\"322\" srcset=\"http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-4.png 732w, http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-4-300x188.png 300w\" sizes=\"(max-width: 512px) 100vw, 512px\" \/><\/a><\/p><\/blockquote>\n<p>When connecting to the <a href=\"http:\/\/gnusb.sourceforge.net\">gnusb<\/a>, at first I thought &#8220;we&#8217;ll only need to listen to the sensor, so I just don&#8217;t connect MOSI and forget about the FET and shit&#8230;&#8221; but this doesn&#8217;t work at all, as the sensor wants to hear &#8220;0xAA 0xFF&#8221; before revealing us its valuable data&#8230;<\/p>\n<p>I didn&#8217;t have a FET around and replaced it with a simple transistor. I also used the ATMEGA16&#8217;s internal pullup instead of R2, and after some fiddling around with byte order and stuff, I was able to get quite nice data, with quite regularly some 0xFFFFs thrown in. But we can safely assume that 0xFFFF is not any useful data, as bit 1 should always be 0, so I just reject these transmissions for the moment. One could do more serious error checking by comparing with the inverted bytes that come afterwards:<\/p>\n<blockquote><p>A data frame consists of 10 bytes:<\/p>\n<p>\u2022 2 start bytes (AAh followed by FFh)<br \/>\n\u2022 2 data bytes (DATA16 \u2013 most significant byte first)<br \/>\n\u2022 2 inverted data bytes (\/DATA16 &#8211; most significant byte first)<br \/>\n\u2022 4 all-Hi bytes<br \/>\n<a href=\"http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-5.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-113\" title=\"Picture 5\" src=\"http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-5.png\" alt=\"\" width=\"493\" height=\"62\" srcset=\"http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-5.png 704w, http:\/\/www.anyma.ch\/blogs\/research\/wp-content\/uploads\/2010\/04\/Picture-5-300x37.png 300w\" sizes=\"(max-width: 493px) 100vw, 493px\" \/><\/a><\/p><\/blockquote>\n<p>Here&#8217;s some code snippets for reading the MLX90316 with the gnusb:<\/p>\n<pre lang=\"c\" line=\"1\">\/\/ \/\/ ==============================================================================\r\n\/\/ Snippets for MLX90316\r\n\/\/ ==============================================================================\r\n\r\n\r\n#include <util\/delay.h>\r\n\r\n\/\/ ==============================================================================\r\n\/\/ Globals\r\n\/\/ ------------------------------------------------------------------------------\r\n\r\nu16             angle;\r\nu08             rx_idx;\r\nu08             rx_buffer[10];\r\n\r\n\/\/ ==============================================================================\r\n\/\/ Talk to MLX90316\r\n\/\/ ------------------------------------------------------------------------------\r\nu08 spi_transmit_byte(u08 byte) {\r\n    SPDR = byte;\r\n    while (!(SPSR & (1<<SPIF))) {}\r\n    return SPDR;\r\n}\r\n\r\n\r\nvoid checkSPI(void) {\r\n\r\n    if (rx_idx == 0) {\r\n        PORTB &#038;= ~(1 << 4);     \/\/ select angle sensor\r\n        _delay_us(6);\r\n        rx_buffer[rx_idx] = spi_transmit_byte(0xAA);\r\n\r\n        rx_idx++;\r\n    } else {\r\n        if (rx_idx < 8) {\r\n            rx_buffer[rx_idx] = spi_transmit_byte(0xFF);\r\n            rx_idx++;       \r\n        } else {\r\n            PORTB |= (1 << 4);      \/\/ deselect angle sensor\r\n            _delay_ms(1);\r\n            rx_idx = 0;\r\n\r\n            if (rx_buffer[3] &#038; 1) {     \/\/ LSB == 0 means error from MLX90316\r\n                u16 temp;\r\n                temp = (rx_buffer[2] << 8) + rx_buffer[3];\r\n                \r\n                if (temp < 0xffff) {    \/\/ angle cannot be 0xffff\r\n                    angle = temp >> 2;  \/\/ bits 0..1 of data doesn't mean anything\r\n                }\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n\r\n\r\n\/\/ ==============================================================================\r\n\/\/ - main\r\n\/\/ ------------------------------------------------------------------------------\r\nint main(void)\r\n{\r\n    \/\/ ------------------------- Initialize Hardware\r\n    \r\n    \/\/PORTB: Serial Communication\r\n    \r\n    DDRB = ~(1 << 6);       \/\/ 1011 1111 - All outputs except MISO \r\n    SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1)|(0<<SPR0) | (0<<CPOL) | (1<<CPHA);      \/\/  enable SPI in Master Mode, clk = fcpu\/16 \r\n    PORTB = (1 << 4);       \/\/ deselect angle sensor\r\n    PORTB |= (1 << 6);\r\n\r\n    \/\/ ------------------------- Main Loop\r\n    while(1) {\r\n        checkSPI();\r\n    }\r\n    return 0;\r\n}\r\n\r\n\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;ve played around with a new sensor. The Melexis MLX90316 can detect the angular position of a magnet. From it&#8217;s datasheet: In combination with the appropriate signal processing, the magnetic flux density of a small magnet (diametral magnetization) rotating above the IC can be measured in a non-contacting way (Figure 3). The angular information [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[14,21,22],"_links":{"self":[{"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/posts\/109"}],"collection":[{"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/comments?post=109"}],"version-history":[{"count":7,"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/posts\/109\/revisions"}],"predecessor-version":[{"id":119,"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/posts\/109\/revisions\/119"}],"wp:attachment":[{"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/media?parent=109"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/categories?post=109"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.anyma.ch\/blogs\/research\/wp-json\/wp\/v2\/tags?post=109"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}