gestion encodeur 5048 par spi

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
PC2ROBOT
Date:
Tue Oct 08 14:59:11 2019 +0000
Commit message:
as5048

Changed in this revision

as5048spi.cpp Show annotated file Show diff for this revision Revisions of this file
as5048spi.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/as5048spi.cpp	Tue Oct 08 14:59:11 2019 +0000
@@ -0,0 +1,132 @@
+#include "as5048spi.h"
+
+As5048Spi::As5048Spi(PinName mosi, PinName miso, PinName sclk, PinName chipselect, int ndevices) :
+    _nDevices(ndevices),
+    _chipSelectN(chipselect),
+    _spi(mosi, miso, sclk)
+{
+    _chipSelectN.write(1);
+    // AS5048 needs 16-bits for is commands
+    // Mode = 1: 
+    //  clock polarity = 0 --> clock pulse is high
+    //  clock phase = 1 --> sample on falling edge of clock pulse
+    _spi.format(16, 1);
+    
+    // Set clock frequency to 1 MHz (max is 10Mhz)
+    _spi.frequency(1000000);
+    
+    _readBuffer = new int[ndevices];
+}
+
+As5048Spi::~As5048Spi()
+{
+    delete [] _readBuffer;
+}
+
+int As5048Spi::degrees(int sensor_result)
+{
+    return mask(sensor_result) * 36000 / 0x4000;
+}
+
+
+int As5048Spi::radian(int sensor_result)
+{
+    return mask(sensor_result) * 62832 / 0x4000;
+}
+
+bool As5048Spi::error(int device)
+{
+    if( device == -1 ) {
+        for(int i = 0; i < _nDevices; ++i) {
+            if( _readBuffer[i] & 0x4000 ) {
+                return true;
+            }
+        }
+    } else if( device < _nDevices ) {
+        return (_readBuffer[device] & 0x4000) == 0x4000;
+    }
+    return false; 
+}
+
+
+void As5048Spi::frequency(int hz) 
+{
+    _spi.frequency(hz);
+}
+
+int As5048Spi::mask(int sensor_result)
+{
+    return sensor_result & 0x3FFF; // return lowest 14-bits
+}
+
+
+void As5048Spi::mask(int* sensor_results, int n)
+{
+    for(int i = 0; i < n; ++i) {
+        sensor_results[i] &= 0x3FFF;
+    }
+}
+
+
+bool As5048Spi::parity_check(int sensor_result)
+{
+    // Use the LSb of result to keep track of parity (0 = even, 1 = odd)
+    int result = sensor_result;
+    
+    for(int i = 1; i <= 15; ++i) {
+        sensor_result >>= 1;
+        result ^= sensor_result;
+    }
+    // Parity should be even
+    return (result & 0x0001) == 0;
+}
+
+const int* As5048Spi::read(As5048Command command)
+{
+    _read(command); // Send command to device(s)
+    return _read(AS_CMD_NOP); // Read-out device(s)
+}
+
+const int*  As5048Spi::read_sequential(As5048Command command)
+{
+    return _read(command);
+}
+
+const int*  As5048Spi::read_angle()
+{  
+    _read(AS_CMD_ANGLE); // Send command to device(s)
+    return _read(AS_CMD_NOP); // Read-out device(s)
+}
+
+const int*  As5048Spi::read_angle_sequential()
+{
+    return _read(AS_CMD_ANGLE); 
+}
+
+
+int* As5048Spi::_read(As5048Command command)
+{
+    if(_nDevices == 1)
+    {
+        // Give command to start reading the angle
+        _chipSelectN.write(0);
+        wait_us(1); // Wait at least 350ns after chip select
+        _readBuffer[0] = _spi.write(command);
+        _chipSelectN.write(1);
+        wait_us(1); // Wait at least 350ns after chip select       
+    } else
+    {
+        // Enable the sensor on the chain
+        _chipSelectN.write(0);
+         wait_us(1); // Wait at least 350ns after chip select
+        for(int i = 0; i < _nDevices; ++i)
+        {
+            _readBuffer[i] = _spi.write(command);
+        }
+        _chipSelectN.write(1);
+        wait_us(1); // Wait at least 350ns after chip select
+    }
+    return _readBuffer;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/as5048spi.h	Tue Oct 08 14:59:11 2019 +0000
@@ -0,0 +1,85 @@
+#include "mbed.h"
+typedef enum {
+    AS_FLAG_PARITY = 0x8000,
+    AS_FLAG_READ = 0x4000,
+} As5048Flag;
+
+typedef enum {
+    AS_CMD_NOP = 0x0000,
+    AS_CMD_ERROR = 0x0001 | AS_FLAG_READ,       // Reads error register of sensor and clear error flags
+    AS_CMD_DIAGNOSTICS = 0x3FFD |  AS_FLAG_READ, // Reads automatic gain control and diagnostics info
+    AS_CMD_MAGNITUDE = 0x3FFE | AS_FLAG_READ,
+    
+    AS_CMD_ANGLE = 0x3FFF| AS_FLAG_PARITY | AS_FLAG_READ,
+} As5048Command;
+
+// Masks for bits in the result of the AS_CMD_DIAGNOSTICS command
+typedef enum {
+    AS_DIAG_CORDIC_OVERFLOW = 0x0200,
+    AS_DIAG_HIGH_MAGNETIC = 0x0400,
+    AS_DIAG_LOW_MAGNETIC = 0x0800,
+} As5048Diagnostics;
+
+
+//! Class for interfacing with the AMS AS5048A magnetic rotary sensor over the SPI-interface.
+class As5048Spi
+{
+public:
+    As5048Spi(PinName mosi, PinName miso, PinName sclk, PinName chipselect, int nDevices = 1);
+    ~As5048Spi();
+    
+    bool error(int device = -1);
+    
+    /// Sets the SPI clock frequency in Hz. Maximum tested frequency is 10MHz.
+    void frequency(int frequency = 1000000);
+    
+    /// Sends a read command to the sensor.
+    const int* read(As5048Command command);
+    
+    /// Sends a read command to the sensor. 
+    /// A call to this function will not directly return the requested value. The
+    /// requested value will be returned in a next read_sequential call. 
+    /// Use this function to read sensor values with minimum speed impact on SPI-bus
+    /// and microcontroller.
+    const int* read_sequential(As5048Command command);
+    
+    /// Performs a single angle measurement on all sensors
+    /// @return Array of raw angle data. To get the 14-bit value representing
+    ///     the angle, apply the mask() to the result.
+    const int* read_angle();
+    
+    /// Performs sequential angle measurements on all sensors. The first time this
+    /// method is called the result is not usefull, the measurement data of the call
+    /// will be returned by the next call to this method.
+    /// @return Array of raw angle data. To get the 14-bit value representing
+    ///     the angle, apply the mask() to the result.
+    const int* read_angle_sequential();
+
+    /// Returns lowest 14-bits
+    static int mask(int sensor_result);
+
+    /// Applies the mask to the first n bytes in the read buffer (for daisychained sensors).
+    static void mask(int* sensor_results, int n);
+    
+    /// Checks if the return value from the sensor has the right parity
+    /// @return true if ok
+    static bool parity_check(int sensor_result);
+    
+    /// Returns an angle from 0 to 36000 (degrees times 100).
+    /// @param sensor_result is one of the values returned by read_angle or read_angle_sequential
+    static int degrees(int sensor_result);
+    
+    /// Returns an angle from 0 to 2*PI*100 
+    /// @param sensor_result is one of the values returned by read_angle or read_angle_sequential
+    static int radian(int sensor_result);
+    
+
+protected:
+    int _nDevices;
+    DigitalOut _chipSelectN;
+    SPI _spi;
+    
+    int* _readBuffer; // Stores the results of the last sequential read
+    
+    int* _read(As5048Command command);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Oct 08 14:59:11 2019 +0000
@@ -0,0 +1,47 @@
+#include "mbed.h"
+#include "as5048spi.h"
+
+#define rayon_roue 0.0045
+#define pi 3.14159
+
+#define intervalle 0.005
+
+As5048Spi sensor(PB_15, PB_14, PB_13, PB_12);   //MOSI, MISO, SCKL, CS
+Serial pc(USBTX, USBRX); // tx, rx
+InterruptIn bouton(PC_13);
+Ticker timer;
+int angle, degrees_avant, degrees_maintenant, degrees_vitesse;
+float vitesse;
+
+void donnee_saisie()
+{
+    const int* angles = sensor.read_angle();
+    angle = angles[0];
+    //Récupération de l'angle précédent
+    degrees_avant = degrees_maintenant;
+        
+    //Aquisition du nouvel angle
+    degrees_maintenant = sensor.degrees(angle)/100;
+        
+    //Calcul de la différence
+    degrees_vitesse = (degrees_maintenant - degrees_avant) / intervalle;
+        
+    vitesse = (rayon_roue * degrees_vitesse * 2 * pi / 360) /*/ (5 + 0.01 / (2 * pi))*/;
+}
+
+void print_speed()
+{
+    timer.detach();
+    //Affichage du résultat
+    pc.printf("rotation = %d degrees/s, vitesse = %.4f mm/s     \r", degrees_vitesse, vitesse * 1000);
+    timer.attach(&donnee_saisie, intervalle); //Lancement de la fonction "donnee_saisie()" toutes les 1 sec
+}
+
+int main() {
+    bouton.rise(&print_speed);
+    timer.attach(&donnee_saisie, intervalle); //Lancement de la fonction "donnee_saisie()" toutes les 1 sec
+    while(1) 
+    {
+        
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Oct 08 14:59:11 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file