mirror of
https://github.com/modelec/actionneurs_STM32.git
synced 2026-03-18 21:40:31 +01:00
POC multiple PCA9685 (use AI btw)
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#define NOMBRE_SERVOS 16
|
||||
#define NOMBRE_POSITIONS_SERVOS 8
|
||||
#define NOMBRE_POSITIONS_ASC 8
|
||||
#define NOMBRE_RELAIS 3
|
||||
|
||||
@@ -23,7 +22,6 @@ typedef struct Actionneurs {
|
||||
bool enJeu;
|
||||
uint16_t armementTirette;
|
||||
uint16_t angleServo[NOMBRE_SERVOS];
|
||||
// uint16_t valeursPositionsServos[NOMBRE_SERVOS][NOMBRE_POSITIONS_SERVOS];
|
||||
uint16_t positionAscenseur;
|
||||
uint16_t valeursPositionsAscenseur[NOMBRE_POSITIONS_ASC];
|
||||
GPIO_TypeDef * relayPorts[NOMBRE_RELAIS];
|
||||
|
||||
113
Core/Src/actio.c
113
Core/Src/actio.c
@@ -3,10 +3,20 @@
|
||||
|
||||
#include "actio.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/* ######################## PARTIE PCA9685 SERVO ########################### */
|
||||
|
||||
#define PCA9685_ADDRESS 0x80
|
||||
#define PCA9685_COUNT 2 // number of boards
|
||||
#define PCA9685_BASE_ADDR 0x40 // A0=A1=A2=0
|
||||
#define PCA9685_SERVOS_PER_BOARD 16
|
||||
#define PCA9685_TOTAL_SERVOS (PCA9685_COUNT * PCA9685_SERVOS_PER_BOARD)
|
||||
|
||||
#define PCA9685_PWM_FREQ 50 // Hz
|
||||
#define SERVO_MIN_PULSE 102 // 0.5 ms
|
||||
#define SERVO_MAX_PULSE 512 // 2.5 ms
|
||||
|
||||
// Datasheet link --> https://cdn-shop.adafruit.com/datasheets/PCA9685.pdf
|
||||
#define PCA9685_MODE1 0x0 // as in the datasheet page no 10/52
|
||||
#define PCA9685_PRE_SCALE 0xFE // as in the datasheet page no 13/52
|
||||
@@ -16,28 +26,38 @@
|
||||
#define PCA9685_MODE1_RESTART_BIT 7 // as in the datasheet page no 14/52
|
||||
|
||||
|
||||
void PCA9685_SetBit(uint8_t Register, uint8_t Bit, uint8_t Value);
|
||||
void PCA9685_SetPWMFrequency(uint16_t frequency);
|
||||
void PCA9685_Init(uint16_t frequency);
|
||||
void PCA9685_SetPWM(uint8_t Channel, uint16_t OnTime, uint16_t OffTime);
|
||||
void PCA9685_SetBit(uint8_t Address, uint8_t Register, uint8_t Bit, uint8_t Value);
|
||||
void PCA9685_SetPWMFrequency(uint8_t Address, uint16_t frequency);
|
||||
void PCA9685_Init(uint8_t Address, uint16_t frequency);
|
||||
void PCA9685_InitAllBoards(uint16_t frequency);
|
||||
void PCA9685_SetPWM(uint8_t Address, uint8_t Channel, uint16_t OnTime, uint16_t OffTime);
|
||||
void PCA9685_SetServoAngle(uint8_t Channel, float Angle);
|
||||
void PCA9685_ContinuousServoRun(uint8_t Channel);
|
||||
void PCA9685_ContinuousServoStop(uint8_t Channel);
|
||||
void PCA9685_ContinuousServoRun(uint8_t Channel); // 360 deg servo
|
||||
void PCA9685_ContinuousServoStop(uint8_t Channel); // 360 deg servo
|
||||
|
||||
extern I2C_HandleTypeDef hi2c1;
|
||||
|
||||
void PCA9685_SetBit(uint8_t Register, uint8_t Bit, uint8_t Value)
|
||||
static inline void servo_to_pca(uint16_t servo,
|
||||
uint8_t *addr,
|
||||
uint8_t *channel)
|
||||
{
|
||||
uint8_t board = servo / PCA9685_SERVOS_PER_BOARD;
|
||||
*channel = servo % PCA9685_SERVOS_PER_BOARD;
|
||||
*addr = PCA9685_BASE_ADDR + board;
|
||||
}
|
||||
|
||||
void PCA9685_SetBit(uint8_t Address, uint8_t Register, uint8_t Bit, uint8_t Value)
|
||||
{
|
||||
uint8_t readValue;
|
||||
// Read all 8 bits and set only one bit to 0/1 and write all 8 bits back
|
||||
HAL_I2C_Mem_Read(&hi2c1, PCA9685_ADDRESS, Register, 1, &readValue, 1, 10);
|
||||
HAL_I2C_Mem_Read(&hi2c1, Address << 1, Register, 1, &readValue, 1, 10);
|
||||
if (Value == 0) readValue &= ~(1 << Bit);
|
||||
else readValue |= (1 << Bit);
|
||||
HAL_I2C_Mem_Write(&hi2c1, PCA9685_ADDRESS, Register, 1, &readValue, 1, 10);
|
||||
HAL_I2C_Mem_Write(&hi2c1, Address << 1, Register, 1, &readValue, 1, 10);
|
||||
HAL_Delay(1);
|
||||
}
|
||||
|
||||
void PCA9685_SetPWMFrequency(uint16_t frequency)
|
||||
void PCA9685_SetPWMFrequency(uint8_t Address, uint16_t frequency)
|
||||
{
|
||||
uint8_t prescale;
|
||||
if(frequency >= 1526) prescale = 0x03;
|
||||
@@ -45,59 +65,86 @@ void PCA9685_SetPWMFrequency(uint16_t frequency)
|
||||
// internal 25 MHz oscillator as in the datasheet page no 1/52
|
||||
else prescale = 25000000 / (4096 * frequency);
|
||||
// prescale changes 3 to 255 for 1526Hz to 24Hz as in the datasheet page no 1/52
|
||||
PCA9685_SetBit(PCA9685_MODE1, PCA9685_MODE1_SLEEP_BIT, 1);
|
||||
HAL_I2C_Mem_Write(&hi2c1, PCA9685_ADDRESS, PCA9685_PRE_SCALE, 1, &prescale, 1, 10);
|
||||
PCA9685_SetBit(PCA9685_MODE1, PCA9685_MODE1_SLEEP_BIT, 0);
|
||||
PCA9685_SetBit(PCA9685_MODE1, PCA9685_MODE1_RESTART_BIT, 1);
|
||||
PCA9685_SetBit(Address, PCA9685_MODE1, PCA9685_MODE1_SLEEP_BIT, 1);
|
||||
HAL_I2C_Mem_Write(&hi2c1, Address, PCA9685_PRE_SCALE, 1, &prescale, 1, 10);
|
||||
PCA9685_SetBit(Address, PCA9685_MODE1, PCA9685_MODE1_SLEEP_BIT, 0);
|
||||
PCA9685_SetBit(Address, PCA9685_MODE1, PCA9685_MODE1_RESTART_BIT, 1);
|
||||
}
|
||||
|
||||
void PCA9685_Init(uint16_t frequency)
|
||||
void PCA9685_Init(uint8_t Address, uint16_t frequency)
|
||||
{
|
||||
PCA9685_SetPWMFrequency(frequency); // 50 Hz for servo
|
||||
PCA9685_SetBit(PCA9685_MODE1, PCA9685_MODE1_AI_BIT, 1);
|
||||
PCA9685_SetPWMFrequency(Address, frequency); // 50 Hz for servo
|
||||
PCA9685_SetBit(Address, PCA9685_MODE1, PCA9685_MODE1_AI_BIT, 1);
|
||||
}
|
||||
|
||||
void PCA9685_SetPWM(uint8_t Channel, uint16_t OnTime, uint16_t OffTime)
|
||||
void PCA9685_InitAllBoards(uint16_t frequency)
|
||||
{
|
||||
for (uint8_t i = 0; i < PCA9685_COUNT; i++) {
|
||||
PCA9685_Init(PCA9685_BASE_ADDR + i, frequency);
|
||||
}
|
||||
}
|
||||
|
||||
void PCA9685_SetPWM(uint8_t Address, uint8_t Channel, uint16_t OnTime, uint16_t OffTime)
|
||||
{
|
||||
uint8_t registerAddress;
|
||||
uint8_t pwm[4];
|
||||
registerAddress = PCA9685_LED0_ON_L + (4 * Channel);
|
||||
// See example 1 in the datasheet page no 18/52
|
||||
pwm[0] = OnTime & 0xFF;
|
||||
pwm[1] = OnTime>>8;
|
||||
pwm[2] = OffTime & 0xFF;
|
||||
pwm[3] = OffTime>>8;
|
||||
HAL_I2C_Mem_Write(&hi2c1, PCA9685_ADDRESS, registerAddress, 1, pwm, 4, 10);
|
||||
uint8_t pwm[4] = {
|
||||
OnTime & 0xFF,
|
||||
OnTime >> 8,
|
||||
OffTime & 0xFF,
|
||||
OffTime >> 8
|
||||
};
|
||||
HAL_I2C_Mem_Write(&hi2c1, Address << 1, registerAddress, 1, pwm, 4, 10);
|
||||
}
|
||||
|
||||
void PCA9685_SetServoAngle(uint8_t Channel, float Angle)
|
||||
{
|
||||
float Value;
|
||||
// 50 Hz servo then 4095 Value --> 20 milliseconds
|
||||
// Centieme de radians
|
||||
// 0 rad --> 0.5 ms(102.4 Value) and 2 PI radians --> 2.5 ms(511.9 Value)
|
||||
Value = (Angle * (511.9 - 102.4) / (/*100 **/ 3.141592)) + 102.4;
|
||||
PCA9685_SetPWM(Channel, 0, (uint16_t)Value);
|
||||
uint8_t addr, ch;
|
||||
servo_to_pca(Channel, &addr, &ch);
|
||||
|
||||
float pwm = (Angle * (SERVO_MAX_PULSE - SERVO_MIN_PULSE)
|
||||
/ (float)M_PI) + SERVO_MIN_PULSE;
|
||||
|
||||
if (pwm < SERVO_MIN_PULSE) pwm = SERVO_MIN_PULSE;
|
||||
if (pwm > SERVO_MAX_PULSE) pwm = SERVO_MAX_PULSE;
|
||||
|
||||
PCA9685_SetPWM(addr, ch, 0, (uint16_t)pwm);
|
||||
}
|
||||
|
||||
void PCA9685_ContinuousServoRun(uint8_t Channel)
|
||||
{
|
||||
PCA9685_SetPWM(Channel, 0, 511);
|
||||
uint8_t addr, ch;
|
||||
servo_to_pca(Channel, &addr, &ch);
|
||||
|
||||
PCA9685_SetPWM(addr, ch, 0, 511);
|
||||
}
|
||||
|
||||
void PCA9685_ContinuousServoStop(uint8_t Channel)
|
||||
{
|
||||
PCA9685_SetPWM(Channel, 0, 307);
|
||||
uint8_t addr, ch;
|
||||
servo_to_pca(Channel, &addr, &ch);
|
||||
|
||||
PCA9685_SetPWM(addr, ch, 0, 307);
|
||||
}
|
||||
|
||||
void PCA9685_LEDOff(uint8_t Channel)
|
||||
{
|
||||
PCA9685_SetPWM(Channel, 0, 0);
|
||||
uint8_t addr, ch;
|
||||
servo_to_pca(Channel, &addr, &ch);
|
||||
|
||||
PCA9685_SetPWM(addr, ch, 0, 0);
|
||||
}
|
||||
|
||||
void PCA9685_LEDOn(uint8_t Channel)
|
||||
{
|
||||
PCA9685_SetPWM(Channel, 0, 1000);
|
||||
uint8_t addr, ch;
|
||||
servo_to_pca(Channel, &addr, &ch);
|
||||
|
||||
PCA9685_SetPWM(addr, ch, 0, 1000);
|
||||
}
|
||||
|
||||
/* ######################## PARTIE TMC2209 STEPPER ########################### */
|
||||
@@ -175,7 +222,7 @@ void step(uint32_t steps, uint32_t delay_us)
|
||||
extern Actionneurs act;
|
||||
|
||||
void initActionneurs(){
|
||||
PCA9685_Init(50);
|
||||
PCA9685_InitAllBoards(PCA9685_PWM_FREQ);
|
||||
HAL_GPIO_WritePin(DIR_PORT, DIR_PIN, GPIO_PIN_SET);
|
||||
TMC2209_init();
|
||||
act.etatLedArmement = 0;
|
||||
|
||||
Reference in New Issue
Block a user