Lancelot77

На Пикабу
129 рейтинг 5 подписчиков 1 подписка 2 поста 1 в горячем
Награды:
5 лет на Пикабу
11

AS5045 и STM32

И снова здравствуйте. Хотел бы продолжить тему про магнитный энкодер AS5045, начатую в моей прошлой статье(https://pikabu.ru/story/as5045_i_arduino_6724136).  Но на этот раз датчик подключается не к ардуино, а к STM32F103C8T6. Так как ардуино оказалась слишком медленной  для  одновременного считывания двух датчиков, выполнение вычислений и многого другого не относящегося к теме. Писался код в System Workbench for STM32 (SW4STM32), но образцы представленного кода должны работать в любой другой среде. Кстати, большей частью эти функции практически полностью перекопированы из библиотеки для ардуино но с оглядкой на частоту STM.

И так начнем с выставления портов ввода-вывода в нужные состояния: CS,CLK - OUTPUT;  DO - INPUT. Названия пинов отражают к какому выводу подключаться на плате датчика.

Теперь тактирование. Оно максимально насколько это возможно и где это возможно:

Вначале нужно объявить следующие дефайны:



#define AS5045_STATUS_OCF 0x10

#define AS5045_STATUS_COF 0x08

#define AS5045_STATUS_LIN 0x04

#define AS5045_STATUS_MAGINC 0x02

#define AS5045_STATUS_MAGDEC 0x01


Встречайте, функция инициализации датчика!


_Bool AS5045_Init()

{

uint8_t count = 0;

while (AS5045_Read(), (_status & AS5045_STATUS_OCF) == 0)

{

if (count > 30)

{

return 0 ; //ошибка инициализации

}

HAL_Delay(5);

count++;

}

return 1;

}


А вот и само считывание статуса датчика и его положения:


uint16_t AS5045_Read()

{


HAL_GPIO_WritePin(GPIOB,CS_PIN_Pin,0); 


uint16_t value = 0;

uint8_t i = 0;


status = 0;

for (i = 0; i <12; i++)

{

HAL_GPIO_WritePin(GPIOB,CLK_PIN_Pin,0);

for(uint8_t i = 0; i < 4; i++){}  //без подобных циклов датчик не

HAL_GPIO_WritePin(GPIOB,CLK_PIN_Pin,1);  //успевает передать данные и на выходе

for(uint8_t i = 0; i < 2; i++) {}  //рандомные числа

value = (value << 1) | HAL_GPIO_ReadPin(DO_PIN_GPIO_Port,DO_PIN_Pin);

}


for ( i = 0 ; i < 6 ; i++)

{

HAL_GPIO_WritePin(GPIOB,CLK_PIN_Pin,0);

for(uint8_t i = 0; i < 4; i++){}

HAL_GPIO_WritePin(GPIOB,CLK_PIN_Pin,1);

for(uint8_t i = 0; i < 2; i++){}


status = (status << 1) | HAL_GPIO_ReadPin(DO_PIN_GPIO_Port,DO_PIN_Pin);

}


HAL_GPIO_WritePin(GPIOB,CS_PIN_Pin,1);


_status = status >> 1 ;


return value ;

}


В принципе это все что я хотел показать сегодня. Тут нет программирования нулевого положения и, возможно, она не самая оптимальная по производительности, но эти функции делают все что мне нужно. Спасибо за внимание!

Показать полностью 2
28

AS5045 и Ардуино

Доброго времени суток. Появилась у меня необходимость сделать считывание угла поворота без какого-либо физического контакта. После некоторых поисков был выбран абсолютный магнитный энкодер AS5045. Он имеет 4096 позиций на один оборот, что соответствует точности примерно 0,088 градуса на позицию. Меня такая точность вполне устраивала и решил брать. Вот тут-то и появилась первая проблема. Заключалась она в том, что на него очень мало толковой информации на русском языке. Забегая вперед, скажу что запустить мне его удалось, именно по этому и захотелось сделать более менее полезную выжимку из того что нашел.

Полазив в даташите и посмотрев фотографии дем-плат от производителя  нарисовал такую схему подключения:

Вторая проблема  это корпус датчика. Датчик поставляется в достаточно маленьком корпусе - SSOP-16, по этому плату делал фоторезистом. Требование по размерам были достаточно жестким  соответственно и элементы взял не большие в корпусе 1206.

Третья проблема это, как ни странно китай. AS5045, как и подобные ему энкодеры требуют  диаметрально намагниченный магнит. Проблема появилась тогда, когда я понял,что китайцы положили не диаметральный магнит а обычный. В принципе это решается установкой магнита на бок, но повторюсь требования по размерам достаточно жесткие. Так что пришлось искать пути обхода. А ларчик просто открывался. Вытащил из мебельной магнитной держалки для дверцы, там и магнит тонкий и если правильно расположить, то все прекрасно работает.

Как сказано в заголовке, подключаться он  будет к плате Ардуино. Для этих целей есть хорошая библиотека (https://github.com/DashZhang/AS5045).  Пример из библиотеки сразу выполняет то что мне и нужно:

[code]

#include <AS5045.h>
// CHANGE THESE AS APPROPRIATE

#define CSpin 2

#define CLKpin 3

#define DOpin 4
AS5045 enc (CSpin, CLKpin, DOpin) ;
// didn't program the OTP

void setup (){

Serial.begin (115200) ;

// NOTE BAUD RATE

if (!enc.begin ()) Serial.println ("Error setting up AS5045") ;}
void loop ()

{/* Serial.print ("value:") ;

Serial.print (enc.read (), DEC) ; 

Serial.print (" ") ; 

Serial.print ("status:") ;

Serial.print (enc.status (), BIN) ; Serial.print (" ") ; 

Serial.print (enc.valid () ? "OK" : "Fault") ; 

Serial.print (" ") ; 

Serial.print ("Z:") ; 

Serial.println (enc.Zaxis ()) ;

*/Serial.print (enc.read () , BIN);Serial.print ("\t");Serial.print (enc.status (), BIN) ;

Serial.print ("\t");

Serial.print ("Angle : ");

Serial.println (enc.read () * 0.08789, DEC);

delay(10);

}

[/code]

В заключении скажу что данная статья не претендует на какое-либо всеобъемлющее учебное пособие и никого не заставляет делать так же как у меня. Написал просто что бы поделиться опытом и помочь тем, у кого возникнут такие же проблемы

Показать полностью 3
Отличная работа, все прочитано!