GithubHelp home page GithubHelp logo

circularbuffer / as5047p Goto Github PK

View Code? Open in Web Editor NEW
8.0 1.0 3.0 5.47 MB

Generic driver for AMS AS5047P magnetic encoder

License: MIT License

C 100.00%
arduino arduino-library as5047p as5047 encoder magnetic-encoder nucleo-f429zi nucleo stm32f4 teensy

as5047p's Introduction

AS5047P driver

Generic driver for AMS AS5047P magnetic encoder written in C. Because the driver was meant to be portable (platform independent), some details related to SPI communication and CS (chip-select) signals must be implemented by the user itself. This implementation takes places in file as5047_hal.c/cpp - 4 simple methods must be implemented - for more details check this file out. SPI and GPIO initialization is assumed to be done outside of the driver. If you want to use AS5047P with Arduino or Nucleo - you can jump to Examples straight away, complete implementation is already done for them.

AS5047P MotorEncoder board frontside AS5047P MotorEncoder board backside

Repository Structure

  • Examples: Driver implementations and examples
    • General: General example with most functions shown
    • Arduino: Driver implementation with an example for Arduino (tested with Teensy 3.2)
    • Nucleo-F429ZI: Driver implementation with an example for Nucleo-F429ZI
  • Images: Images
  • Library: AS5047P generic driver library

How to run library on Arduino

  1. Import example to your project
  2. Adjust method AS5047P_SelectSPIAndGPIO() in as5047_hal.cpp for your needs (CS pin selection)
  3. Run

How to run library on Nucleo (F429ZI)

  1. Import example to your project
  2. Adjust method AS5047P_SelectSPIAndGPIO() in as5047_hal.c for your needs (CS pin selection, SPI handler selection)
  3. Run

How to run library on the other platforms

To make the library working with your platform you need to:

  1. Import library to your project
  2. Configure GPIO for CS signals
  3. Configure SPI with these parameters:
  • SPI MODE 1 (CPOL = 0, CPHA = 1)
  • SCK max. 10Mhz (11.25Mhz worked also fine but not recommended)
  • Data size: 16 bits
  • Bits order: MSB first
  • CS signals handled by software
  1. Implement following methods from as5047_hal.c file:
  • AS5047P_HAL_Delay_ms: used for generating delay in miliseconds
  • AS5047P_HAL_SPI_TxRx: used for full-duplex SPI transmission
  • AS5047P_HAL_GPIO_Write: used for setting/clearing CS pins
  • AS5047P_SelectSPIAndGPIO: used for selecting SPI periphery and CS signal (see examples for Arduino/Nucleo)
  • AS5047P_HAL_Debug: used for debug purposes. This is an option.
  1. Create encoder's instance, initialize, set zero position (calibrate) and use :
// Create encoder's instance:
AS5047P_Instance encInstanceA;
// Initialize:
AS5047P_Init(&encInstanceA, 0);
// Set zero position:
AS5047P_SetZeroPosition(&encInstanceA);
// Use:
encPositionA = AS5047P_ReadPosition(&encInstanceA, AS5047P_OPT_ENABLED);

Features

  • SPI communication monitoring (parity bit check)
  • SPI's slave reachibility test (by requesting non-zero value register)
  • Position value validation (magnetic field strength, CORDIC overflow, etc.) when AS5047P_ReadPosition() method is used.
  • Zero position calibration possible with AS5047P_SetZeroPosition() method.
  • Any register read/write possible with AS5047P_ReadRegister() and AS5047P_WriteRegister methods.
  • OTP burn possible

Simple example

#include "as5047p.h"

  AS5047P_Instance encInstanceA = {0};
  AS5047P_Result encPositionA;

int main(void)
{
   //--- Initialize GPIO
   //--- Initialize SPI
   
   //--- Initialize encoder and bind id number to the instance.
   AS5047P_Init(&encInstanceA, 0); // Bind encoder with id = 0

   //--- Set current encoder position as new zero (AS5047P_ZPOSL, AS5047P_ZPOSM)
   AS5047P_SetZeroPosition(&encInstanceA);

   //--- Any of the above returned error.
   if ( AS5047P_ErrorPending(&encInstanceA) )
   {
       while(1)
       {}// Sorry Joe, no luck today.
   }

   while (1)
   {
     encPositionA = AS5047P_ReadPosition(&encInstanceA, AS5047P_OPT_ENABLED);
     if( AS5047P_ErrorPending(&encInstanceA) )
     {
     	//--- Acknowledge error 
	AS5047P_ErrorAck(&encInstanceA);
     }     
     //--- Do something
   }

}

All features example

#include "as5047p.h"

  AS5047P_Instance encInstanceA = {0};
  AS5047P_Result encPositionA;

int main(void)
{
   //--- Initialize GPIO
   //--- Initialize SPI
   
   //--- Initialize encoder and bind id number to the instance.
   AS5047P_Init(&encInstanceA, 0); // Bind encoder with id = 0

   //--- Set registers SETTINGS1, SETTINGS2, ZPOSL, ZPOSM to their factory defaults
   //--- (in this way ignoring OTP memory loaded values).
   AS5047P_SetFactorySettings(&encInstanceA);

   //--- Set current encoder position as new zero (AS5047P_ZPOSL, AS5047P_ZPOSM)
   AS5047P_SetZeroPosition(&encInstanceA);

   //--- Change ABI resolution to 4096 Steps per revolution (ABIRES, ABIBIN)
   AS5047P_SetABIResolution(&encInstanceA, AS5047P_ABIRES_4096);

   /***************************************************************************
    * The rest of configuration is done by working directly on registers' contents.
    ***************************************************************************/

   //--- Set field UVWPP of register AS5047P_SETTINGS2 to value 3 (meaning 4 pole pairs - datasheet).
   AS5047P_SetFieldInRegister(&encInstanceA, AS5047P_SETTINGS2 , AS5047P_SETTINGS2_UVWPP, 3);

   //--- Set fields COMP_I_ERR_EN and COMP_H_ERR_EN of register AS5047P_ZPOSL to 1
   //--- (meaning: enable the contribution of MAGH and MAGL to the error flag.
   AS5047P_SetFieldInRegister(&encInstanceA, AS5047P_ZPOSL , AS5047P_ZPOSL_COMP_I_ERR_EN, 1);
   AS5047P_SetFieldInRegister(&encInstanceA, AS5047P_ZPOSL , AS5047P_ZPOSL_COMP_H_ERR_EN, 1);

   //--- Set field PWMon of register AS5047P_SETTINGS1 to 1 (meaning: turn on PWM output).
   AS5047P_SetFieldInRegister(&encInstanceA, AS5047P_SETTINGS1 , AS5047P_SETTINGS1_PWMON, 1);

   //--- Set field HYS of register AS5047P_SETTINGS2 to 3 (meaning: ...).
   AS5047P_SetFieldInRegister(&encInstanceA, AS5047P_SETTINGS2 , AS5047P_SETTINGS2_HYS, 3);

   //--- Any of the above returned error.
   if ( AS5047P_ErrorPending(&encInstanceA) )
   {
       while(1)
       {}// Sorry Joe, no luck today.
   }

   //--- Burn OTP and verify. Current content of registers
   //--- is burnt to OTP memory. Second input is enable signal,
   //--- must be 666, otherwise OTP burn WILL NOT take place.
   AS5047P_BurnOTP(&encInstanceA, 000); // Replace '000' with '666' if you're really sure to burn OTP.

   while (1)
   {
     encPositionA = AS5047P_ReadPosition(&encInstanceA, AS5047P_OPT_ENABLED);

     if( !AS5047P_ErrorPending(&encInstanceA) )
     {
		//--- Print current position
		printf("Encoder ID[%d]> Position: %d\n",AS5047P_GetID(&encInstanceA), encPositionA);
     }
     else
     {
		//--- Print error message
		printf("Encoder ID[%d]> Error %d: %s\n",AS5047P_GetID(&encInstanceA),AS5047P_GetError(&encInstanceA).errorCode, AS5047P_GetError(&encInstanceA).msg);
     }

     //--- Acknowledge error if user button pressed
     if( UserButtonPressed )
     {
		AS5047P_ErrorAck(&encInstanceA);
     }

     //--- Delay 100ms (for printf)
     delay_ms(100);
   }

}

as5047p's People

Contributors

circularbuffer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

as5047p's Issues

Getting Error3: Parity bit error occurred in Rx frame

Hello CircularBuffer,

I am trying to use your library for the AS5047P and I am running into a bit of a problem. I get the error, "Error 3: Parity bit error occurred in Rx frame".

I am trying to use this with an STM32G431RB Nucleo-64 dev board and STM32CubeIDE 1.6.1. I have the sensor connected to SPI1 and I have the VCP setup to debug as in your example. I have walked through your instructions of setting up the 5 functions and also configuring the SPI. In my main.c I then call AS5047P_Init(&encInstanceA, 0);, AS5047P_SetFactorySettings(&encInstanceA); and AS5047P_SetZeroPosition(&encInstanceA); to set the sensor up. My logic analyzer shows that I am both transmitting data from the MCU and receiving responses from the sensor. But as soon as I call encPositionA = AS5047P_ReadPosition(&encInstanceA, AS5047P_OPT_ENABLED); I get Error 3 and the result of encPositionA is -1. Everything complies and there are no build errors.

Would you have an idea of what I am doing wrong? I feel like this is a simple fix, but I just can't see it. Any hints of help would be appreciated.

Sincerely,

Dylan

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.