Drivers

Périphériques

peripheriques.svg

Brochage


Mesure de la Position / Vitesse

Le codeur Incrémental

  • Le Codeur incrémental est un capteur de position.
  • Son axe est solidaire de celui de la machine.
  • Il fait tourner un disque comportant des zones transparentes et opaques.
  • une LED émet un rayonnement capté par des photodiodes au passage de chaque zone transparente du disque.

La présence de deux leds permet de déterminer le sens de rotation.
Un signal supplémentaire (Index) est mis à 1 à chaque tour.

hedl5540.png

TPE-Codeur-incremental.jpg

codeur_inc_1.gif

codeur_inc_2.gif

Position

  • La position est accumulée dans un timer dont l’horloge est (A xor B)
  • Ce timer est remis à 0 à chaque tour (grâce au signal Index)
  • La position absolue correspond à INDX*(CNT_PER_ROUND)+CNT

encoder_periph.svg

mes_position.svg

Vitesse

  • La vitesse est la dérivée de la position.
  • Numériquement cela se traduit par SPEED=(POS_act-POS_prec)/Te
  • Ce résultat est faux au moment de la remise à zéro du timer.
  • L’algorithme suivant est donc nécessaire :

SENS DIRECT

mes_vitesse_direct.svg

mes_vitesse_algo.svg

  • Speed=10000-5000=5000 –> Speed>0 –> Speed<16384 –> Speed=10000
  • Speed=25000-20000=5000 –> Speed>0 –> Speed<16384 –> Speed=10000
  • Speed=2232-30000=-27768 –> Speed<0 –> Speed<-16384 –> Speed=-27768+32768=5000 –> Speed=10000

SENS INVERSE

mes_vitesse_inverse.svg

  • Speed=5000-10000=-5000 –> Speed<0 –> Speed>-16384 –> Speed=-10000
  • Speed=20000-25000=-5000 –> Speed<0 –> Speed>-16384 –> Speed=-10000
  • Speed=30000-2232=27768 –> Speed>0 –> Speed>16384 –> Speed=27768-32768=-5000 –> Speed=-10000
code quadencoder
/*
 * quadEncoder.h
 *
 *  Created on: 30 juin 2016
 *      Author: kerhoas
 */

#ifndef INC_QUADENCODER_H_
#define INC_QUADENCODER_H_



#include "main.h"

void quadEncoder_Init(void);
uint16_t quadEncoder_GetPos16(void);
int32_t quadEncoder_GetPos32(void);
int16_t quadEncoder_GetSpeed(void);
void quadEncoder_CallbackIndexZ(void);
void quadEncoder_PosCalc(int*);


#endif /* INC_QUADENCODER_H_ */




/*
 * QuadEncoder.c
 */
#include "quadEncoder.h"
#define COUNT_PER_ROUND 2000
#define MAX_CNT_PER_REV (COUNT_PER_ROUND * 4 - 1)
#define MAX_COUNT (int)(((unsigned long)MAX_CNT_PER_REV*4096)/1000)
#define HALF_MAX_COUNT (MAX_COUNT>>1)

TIM_HandleTypeDef    TimEncoderHandle;

static int indexZ=-1;


int first_index_reached = 0;

//================================================================
//		TIMER INIT
//================================================================

void quadEncoder_Init(void)
{
	TIM_Encoder_InitTypeDef sConfig;

	TimEncoderHandle.Instance = TIM2;
	TimEncoderHandle.Init.Prescaler = 0;
	TimEncoderHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
	TimEncoderHandle.Init.Period = COUNT_PER_ROUND*4;
	TimEncoderHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

	sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
	sConfig.IC1Polarity = TIM_INPUTCHANNELPOLARITY_RISING;
	sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
	sConfig.IC1Prescaler = TIM_ICPSC_DIV4;
	sConfig.IC1Filter = 0x0F;
	sConfig.IC2Polarity = TIM_INPUTCHANNELPOLARITY_RISING;
	sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;//TIM_ICSELECTION_DIRECTTI; //TIM_TI1SELECTION_XORCOMBINATION
	sConfig.IC2Prescaler = TIM_ICPSC_DIV4;
	sConfig.IC2Filter = 0x0F;

	HAL_TIM_Encoder_Init(&TimEncoderHandle, &sConfig);
	HAL_TIM_Encoder_Start(&TimEncoderHandle,TIM_CHANNEL_1);
	HAL_TIM_Encoder_Start(&TimEncoderHandle,TIM_CHANNEL_2);
}
//================================================================
//		POSITION LEFT CALC
//================================================================
void quadEncoder_PosCalc(int* AngPos)
{

int POSCNTcopy = 0;
POSCNTcopy = (int)TIM2->CNT;
AngPos[1] = AngPos[0];
AngPos[0] = (unsigned int)(((unsigned long)POSCNTcopy * 4096)/1000); // 0 <= POSCNT <= 4999 to 0 <= AngPos <= 32767
}
//================================================================
//		POSITION LEFT 16 BITS
//================================================================
uint16_t quadEncoder_GetPos16(void)
{
	uint16_t Pos = 0;
	Pos=TIM2->CNT;
	return Pos;
}
//================================================================
//		POSITION LEFT 32 BITS	(pos 16 bits + nombre de tours)
//================================================================
int32_t quadEncoder_GetPos32(void)
{
	int32_t  PosL = 0;
	PosL=indexZ*2*COUNT_PER_ROUND + (int32_t) quadEncoder_GetPos16();
	return -PosL;
}
//================================================================
//		SPEED LEFT
//--> get pos and reset timer ; must be called every Te
//================================================================
int16_t quadEncoder_GetSpeed(void)
{
	static int AngPos[2] = {0,0};
	static int16_t Speed=0;


	quadEncoder_PosCalc(AngPos);
	Speed = AngPos[0] - AngPos[1];
	if (Speed >= 0)
	{
		if (Speed >= HALF_MAX_COUNT)
			{
			Speed = Speed - MAX_COUNT;
			}
	}
	else
	{
		if (Speed < -HALF_MAX_COUNT)
			{
			Speed = Speed + MAX_COUNT;
			}
	}
	Speed = Speed << 1;		//*2
	return Speed;
}
//================================================================
//		MAJ indexZ Left
//================================================================
void quadEncoder_CallbackIndexZ()
{
				if (__HAL_TIM_DIRECTION_STATUS(&TimEncoderHandle)==1)
				{
					indexZ--;
				}
				else
				{
					indexZ++;
				}
				__HAL_TIM_SetCounter(&TimEncoderHandle, 0);		// RAZ Counter
				HAL_TIM_Encoder_Start(&TimEncoderHandle,TIM_CHANNEL_1);
				HAL_TIM_Encoder_Start(&TimEncoderHandle,TIM_CHANNEL_2);

				first_index_reached = 1;
}
//================================================================




Mesure des Courants

mes_courants.svg

driver ADC
/*
 * drv_adc.h
 *
 *  Created on: 25 oct. 2016
 *      Author: kerhoas
 */

#ifndef SRC_DRV_DRV_ADC_H_
#define SRC_DRV_DRV_ADC_H_

#include "main.h"

void adc1_Init(void);
uint32_t adc_getPotValue(void);
uint32_t adc_getIaValue(void);
uint32_t adc_getIbValue(void);


typedef struct {
  uint16_t* RegularValueBuffer;        /*!< Regular buffer for converted value*/
  uint16_t* InjectedValueBuffer;       /*!< Injected buffer for converted value*/
  uint32_t RegularCurrentRank;         /*!< Regular current rank*/
  uint32_t InjectedCurrentRank;        /*!< Injected current rank*/
  uint32_t nbRegChannel;               /*!< Number of regular channel*/
  uint32_t nbInjChannel;               /*!< Number of injected channel*/
  uint8_t useDMA;                      /*!< DMA aquisition mode */
  void (* ItEOCFcn)(void);
  void (* ItJEOCFcn)(void);
  void (* ItAWDFcn)(void);
  void (* ItOVRFcn)(void);
} ADC_DataLinkTypeDef;

extern uint16_t G_NbAdcConf;           /* Number of ADC configured */

/* Array of ADC data information */
extern ADC_DataLinkTypeDef* G_ADC_Data[2];
extern ADC_HandleTypeDef* G_ADC_Handler[2];

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

/* ADC1 Regular channel Converted value buffer */
extern uint16_t ADC1_RegularConvertedValue[3];

/* ADC1 data information*/
extern ADC_DataLinkTypeDef ADC1_DataLink;


#endif /* SRC_DRV_DRV_ADC_H_ */
/*
 * drv_adc.c
 *
 *  Created on: 25 oct. 2016
 *      Author: kerhoas
 */

#include "drv_adc.h"

uint16_t G_NbAdcConf = 0;              /* Number of ADC configured */

ADC_DataLinkTypeDef* G_ADC_Data[2];
ADC_HandleTypeDef* G_ADC_Handler[2];
uint16_t ADC1_RegularConvertedValue[3];
ADC_DataLinkTypeDef ADC1_DataLink;

extern uint16_t g_ADCBuffer[3];
extern uint16_t potentiometre, Ia_mes, Ib_mes;

void adc1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig;

  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION12b;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = DISABLE; // Conversions Triggered
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.ExternalTrigConv =ADC_EXTERNALTRIGCONV_T3_CC1;

  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 3;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  HAL_ADC_Init(&hadc1);

  sConfig.Channel = ADC_CHANNEL_9; // POT VALUE
  sConfig.Rank = 3;
  sConfig.SamplingTime =  ADC_SAMPLETIME_84CYCLES;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);

  sConfig.Channel = ADC_CHANNEL_0; // Ia VALUE
  sConfig.Rank = 1;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);

  sConfig.Channel = ADC_CHANNEL_11; // Ib VALUE
  sConfig.Rank = 2;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);

  hdma_adc1.Instance = DMA2_Stream0;
  hdma_adc1.Init.Channel = DMA_CHANNEL_0;
  hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
  hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
  hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  hdma_adc1.Init.Mode = DMA_CIRCULAR;
  hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
  hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  HAL_DMA_Init(&hdma_adc1);

  __HAL_LINKDMA(&hadc1,DMA_Handle,hdma_adc1);
}


//============================================================================
//		INTERRUPTION ADC
//============================================================================
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
//	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, 1);
	Ia_mes	 = g_ADCBuffer[0];
	Ib_mes	=  g_ADCBuffer[1];
	potentiometre =  g_ADCBuffer[2];

//	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, 0);
}
//============================================================================

Multitâche

Le RTOS FreeRTOS est utilisé pour gérer la synchronisation des tâches FAST_TASK (la plus prioritaire) et PRINT_TASK

  • tickTimer impose la fréquence d’échantillonage Fe (période Te=45µs)
  • à chaque fois que tickTimer atteint 2250, une conversion Analogique-Numérique est réalisée (pour récupérer les courants).
  • à chaque interruption fin de comptage, un jeton est donné au sémaphore SEM. Cela libère la tache FAST TASK.
  • La tache FAST Task est chargée de calculer les nouveaux rapports cycliques.
  • lorsque FAST_TASK reprend un jeton à SEM, elle est mise en attente.
  • PRINT_TASK peut alors s’exécuter pour envoyer des informations sur la liaison série.
  • pwmTimer Evolue à la même fréquence que tickTimer ; le rapport cyclique est représenté par le registre CCR.

multitache.svg

main

#include <stdint.h>
#include <stdio.h>

#include "stm32f4xx_hal.h"
#include "stm32f4xx.h"
#include "stm32f4xx_hal_conf.h"


#include "drv_adc.h"
#include "stm32F446_nucleo_ihm07m1_enib.h"
#include "drv_uart.h"
#include "SystemClock.h"
#include "calc.h"
#include "config.h"
#include "tickTimer.h"
#include "drv_can.h"

#include "pulseGenerator.h"

#include "sendtoXcos.h"
#include "quadEncoder.h"
#include "pwmTimer.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

#include "X2C.h"


extern ADC_HandleTypeDef hadc1;
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim4;
extern UART_HandleTypeDef huart2;



typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned char uint8_t;
typedef signed char int8_t;

#include "main.h"
#include "motorControl.h"


#define OFFSET_THETA	800

extern void SystemClock_Config(void);
extern void findFirstIndex();
extern void MX_TIM1_Init(void);
extern void MC_FOC_Start_PWM_driving(void);
extern void  MC_FOC_EnableInputs();

extern int32_t quadPos, theta_elec;
extern q31_t iq_mes;
extern int first_index_reached;
extern TIM_HandleTypeDef    TimHandle_period, TimHandle_adc, h_TimSlowTask;
extern 	uint16_t	potentiometre;
extern uint16_t Ia_mes, Ib_mes, Ic_mes;
extern int32_t	Ia_mes_ext, Ib_mes_ext;
extern 	q31_t alpha, beta, sinVal, cosVal;

int16_t speed_mes;

uint32_t pot;
int16_t Ia_bias, Ib_bias;
uint16_t g_ADCBuffer[3];
int32_t pulse=-1;

void (*rxCompleteCallback) (void);
void can_callback(void);

CAN_Message      rxMsg;
CAN_Message      txMsg;
long int        counter = 0;

uint8_t* aTxBuffer[2];

xSemaphoreHandle xSemaphore_Fast = NULL;
xSemaphoreHandle xSemaphore_Slow = NULL;
xQueueHandle qh = NULL;
extern q31_t  iq_err, iq_cde;


int32_t theta_elec_ex;

//int32_t tab_speed[5000];
int FC1, FC2;

//============================================================================
static void Fast_Task(void *pvParameters)
{
	vTaskDelay(5);
	Ia_bias=Ia_mes;
	Ib_bias=Ib_mes;
	int cnt_40 = 40;
	int16_t signe;
	int state=0;


	for (;;)
	{

		if (first_index_reached == 0)
			{

			#if USE_MOTOR
				findFirstIndex();	// stm32F446_nucleo_ihm07m1_enib.c
			#else
				first_indeInports.pot=potentiometre; break;x_reached = 1;
			#endif

			}
		else
			{

		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, 1);		// PC9 MES PER 1 --> To profile function
		//---------------------------------------------------

		Inports.pot=potentiometre;
		Inports.pulse=pulse;



		//---------------------------------------------------
 		quadPos = quadEncoder_GetPos16();			// cf quadEncoder.c
		signe=((int16_t)quadPos+OFFSET_THETA);

		if (signe>8000)
		{quadPos = quadPos + OFFSET_THETA - 8000;}
		else
		{quadPos = quadPos + OFFSET_THETA;}

		theta_elec=quadPos%2000 ;	//theta_elec=quadPos/POLE_PAIR; // [0 8000] --> [0 2000]
		theta_elec_ex=(int32_t)(theta_elec)*16;

		Inports.theta_elec=theta_elec_ex;
		//........................................................

		Ia_mes_ext=((int32_t)Ia_mes)-Ia_bias;
		Ib_mes_ext=((int32_t)Ib_mes)-Ib_bias;


		Inports.Ia=Ia_mes_ext;
		Inports.Ib=Ib_mes_ext;

		//........................................................

	    if (cnt_40 == 0)
	    {
	    	speed_mes=-quadEncoder_GetSpeed();
	    	Inports.speed=speed_mes;

	        cnt_40 = 40;

	    }

	    cnt_40--;

 		X2C_Update();


 		// Update Duty Cycle
		pwmSetDutyCycle(*Outports.pduty_1,*Outports.pduty_2,*Outports.pduty_3);

		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, 0);		// PC9

			}

	xSemaphoreTake( xSemaphore_Fast, portMAX_DELAY );
	}
}
//============================================================================
static void Print_Task(void *pvParameters)
{
	txFrame txf;
	for (;;)
	{
		txf.data0 = potentiometre;
		txf.data1 = pulse;
		txf.data2 = speed_mes;
		txf.data3 =Inports.Ia;
		txf.data4 = *Outports.pIQ_mes;
		txf.data5 = *Outports.pduty_1;
		txf.data6 =0;
		sendtoXcos(txf);
	}
}
//============================================================================
//	>>>>>>>>>>>>>>>>>>>>>>>>>>	MAIN  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//============================================================================
int main(void)
{
  HAL_Init();
  SystemClock_Config();

  adc1_Init();
  uart2_Init();
  quadEncoder_Init();
  pwmTimer_Init();
  tickTimerInit(PWM_COUNT_PERIOD);

  first_index_reached=0;
  MC_FOC_Nucleo_Init();
  MC_FOC_Start_PWM_driving();
  pwmSetDutyCycle(420,420,420);
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_SET); //BSP_X_NUCLEO_FAULT_LED_ON();
  MC_FOC_EnableInputs();

#if USE_PULSE
  pulseGenerator_Init(3000);
#endif

  can_Init();		// Default CAN BAUDRATE : 500kb/s
  can_Filter_disable(); // Accept everybody
  can_IrqInit();
  can_IrqSet(&can_callback);

  txMsg.id=0x7FF;
  txMsg.data[0]=1;
  txMsg.data[1]=2;
  txMsg.len=2;
  txMsg.format=CANStandard;
  txMsg.type=CANData;

  can_Write(txMsg);		// TEST CAN BUS
  HAL_Delay(100);

  X2C_Init();

  //--------------------------------------------
  // 				FREERTOS
  //--------------------------------------------

  potentiometre =450;

  xTaskCreate( Fast_Task, ( const portCHAR * ) "Fast_Task", 512, NULL, tskIDLE_PRIORITY+3, NULL );
  xTaskCreate( Print_Task, ( const portCHAR * ) "Print_Task", 512, NULL, tskIDLE_PRIORITY+1, NULL );

  vSemaphoreCreateBinary(xSemaphore_Fast);
  xSemaphoreTake( xSemaphore_Fast, portMAX_DELAY );

  vSemaphoreCreateBinary(xSemaphore_Slow);
  xSemaphoreTake( xSemaphore_Slow, portMAX_DELAY );


  __HAL_TIM_ENABLE_IT(&TimHandle_period,TIM_IT_UPDATE); // ??
  HAL_TIM_OC_Start(&TimHandle_period, TIM_CHANNEL_1);
  HAL_ADC_Start_DMA(&hadc1, g_ADCBuffer, 3);

  vTaskStartScheduler();

  return 0;
}
//============================================================================
//		INTERRUPTION CALLBACK ON TIMER PERIOD
//============================================================================
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

	static BaseType_t xHigherPriorityTaskWoken;

	if (htim->Instance==TIM3)	// Fast Task
	{
		xSemaphoreGiveFromISR( xSemaphore_Fast,&xHigherPriorityTaskWoken );
		portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
	}


	if (htim->Instance==TIM5)
	{
		if (pulse==0)
		{	pulse=potentiometre;}
		else
		{	pulse=0; }
	}

}
//====================================================================
//			INTERRUPT CALLBACK ON CAN RECEIVE
//====================================================================
void can_callback(void)
{
	CAN_Message msg_rcv;
	int i=0;

	can_Read(&msg_rcv);
	txMsg.id=0x55;			// Identifiant du message à envoyer

	for(i=0;i<8;i++)
	{
	txMsg.data[i]=msg_rcv.data[i]+1;
	}
	txMsg.len=8;			// Nombre d'octets à envoyer
	txMsg.format=CANStandard;
	txMsg.type=CANData;

	can_Write(txMsg);
}
//============================================================================
//		INTERRUPTION EXTI --> When we push blue button
//============================================================================
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin==GPIO_PIN_13)
	{
	 MC_FOC_Nucleo_Init();
	 first_index_reached=0;
	 MC_FOC_Start_PWM_driving();
	 pwmSetDutyCycle(420,420,420);
	 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_SET);//BSP_X_NUCLEO_FAULT_LED_ON();
	 MC_FOC_EnableInputs();
	 __HAL_TIM_ENABLE_IT(&TimHandle_period,TIM_IT_UPDATE); // ??
	 HAL_TIM_OC_Start(&TimHandle_period, TIM_CHANNEL_1);

	}
	else if (GPIO_Pin==GPIO_PIN_10)
	{
	 quadEncoder_CallbackIndexZ();
	}

	else if (GPIO_Pin==GPIO_PIN_4)
	{
		FC1=1;
		FC2=0;//term_printf("FC1\n\r");
	}
	else if (GPIO_Pin==GPIO_PIN_5)
	{
		//term_printf("FC2\n\r");

		FC1=0;
		FC2=1;//term_printf("FC1\n\r");
	}

}
//=================================================================
// Called if stack overflow during execution
extern void vApplicationStackOverflowHook(xTaskHandle *pxTask,
		signed char *pcTaskName)
{
	//term_printf("stack overflow %x %s\r\n", pxTask, (portCHAR *)pcTaskName);
	/* If the parameters have been corrupted then inspect pxCurrentTCB to
	 * identify which task has overflowed its stack.
	 */
	for (;;) {
	}
}
//=================================================================
//This function is called by FreeRTOS idle task
extern void vApplicationIdleHook(void)
{
}
//=================================================================
// brief This function is called by FreeRTOS each tick
extern void vApplicationTickHook(void)
{
//	HAL_IncTick();
}
//================================================================
#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif
PWM Timer
/*
 * pwmTimer.h
 *
 *  Created on: 25 oct. 2016
 *      Author: kerhoas
 */

#ifndef INC_PWMTIMER_H_
#define INC_PWMTIMER_H_

#include "main.h"

void pwmTimer_Init(void);

TIM_HandleTypeDef htim1;

#endif /* INC_PWMTIMER_H_ */
/*
 * pwmTimer.c
 *
 *  Created on: 25 oct. 2016
 *      Author: kerhoas
 */


#include "pwmTimer.h"
#include "stm32f4xx_hal.h"

//================================================================
void pwmTimer_Init(void)
{
  TIM_SlaveConfigTypeDef sSlaveConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;
  TIM_ClearInputConfigTypeDef sClearInputConfig;
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED2;//TIM_COUNTERMODE_CENTERALIGNED2;
  htim1.Init.Period = PWM_COUNT_PERIOD-1;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  HAL_TIM_Base_Init(&htim1);
  HAL_TIM_PWM_Init(&htim1);
  //--------------------------------------------------------
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
  sSlaveConfig.InputTrigger = TIM_TS_ITR3; // TRIGGER FROM TIMER 3
  HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

  //------------------------------------------------------------

  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 5;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
  HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);

  //------------------------------------------------------------
  sConfigOC.OCMode = TIM_OCMODE_PWM2; // _PWM1 : Clear on compare match / _PWM2 : Set on compare match
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
  HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2);
  HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3);

  sClearInputConfig.ClearInputSource = TIM_CLEARINPUTSOURCE_ETR;
  sClearInputConfig.ClearInputPolarity = TIM_CLEARINPUTPOLARITY_NONINVERTED;
  sClearInputConfig.ClearInputPrescaler = TIM_CLEARINPUTPRESCALER_DIV1;
  sClearInputConfig.ClearInputFilter = 0;
  HAL_TIM_ConfigOCrefClear(&htim1, &sClearInputConfig, TIM_CHANNEL_1);
  HAL_TIM_ConfigOCrefClear(&htim1, &sClearInputConfig, TIM_CHANNEL_2);
  HAL_TIM_ConfigOCrefClear(&htim1, &sClearInputConfig, TIM_CHANNEL_3);
}
//================================================================
Tick Timer
/*
 * tickTimer.h
 *
 *  Created on: 30 juin 2016
 *      Author: kerhoas
 */

#ifndef INC_TICKTIMER_H_
#define INC_TICKTIMER_H_

#include "main.h"

void tickTimerInit(uint16_t);



#endif /* INC_TICKTIMER_H_ */
#include "tickTimer.h"
TIM_HandleTypeDef    TimHandle_period;

//================================================
//		TIMER 3 INIT : FAST TRACK UPDATE
//================================================

void tickTimerInit(uint16_t pwm_count_period)
{
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  TimHandle_period.Instance = TIM3;
  TimHandle_period.Init.Prescaler = 0;
  TimHandle_period.Init.Period = 2*PWM_COUNT_PERIOD-3;
  TimHandle_period.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  TimHandle_period.Init.CounterMode = TIM_COUNTERMODE_UP;//TIM_COUNTERMODE_CENTERALIGNED1;
  TimHandle_period.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  TimHandle_period.Init.RepetitionCounter = 0;
  HAL_TIM_Base_Init(&TimHandle_period);
  HAL_TIM_PWM_Init(&TimHandle_period);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
  HAL_TIMEx_MasterConfigSynchronization(&TimHandle_period, &sMasterConfig);

  sConfigOC.OCMode = TIM_OCMODE_PWM1; // TIM_OCMODE_PWM2; ??  PWM1 : Clear on compare match / PWM2 : Set on compare match
  sConfigOC.Pulse =2250;//2250;//2200;//2100;//2000;		// Pour régler le moment de la conversion anlogique --> Numérique
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  HAL_TIM_PWM_ConfigChannel(&TimHandle_period, &sConfigOC, TIM_CHANNEL_1);
}

//================================================