[STM32] HALライブラリ位置PID調整制御出力電圧(超詳細)

  この記事では、STM32CubeMXを使用してADC、DMA、DAC、USARTを構成し、PID位置アルゴリズムを使用して出力電圧のAD収集を実現し、PIDアルゴリズムを介してDACを調整して必要な電圧値を取得します。
主な知識の説明:

  1. PIDとは何ですか?PIDが必要な理由
  2. STM32CubeMXの作成
  3. STM32ソースコード

1. PIDとは何ですか?PIDが必要な理由

  以下は、PID制御の全体的なブロック図です。プロセスは次のように説明されます。出力ターゲットを設定し、フィードバックシステムが出力値を返します。ターゲットと一致しない場合はエラーが発生します。PIDは入力値を調整しますこのエラーに応じて、出力が設定値に達するまで。

  質問:では、なぜPIDが必要なのですか?たとえば、DACを使用して1.65Vの電圧を出力したい場合、直接実行することはできませんか?

  ここで、最初に目標について説明する必要があります。これは、すべての制御が出力が設定に到達できることだけであるためです。つまり、目標電圧値を設定した場合、どのような電圧値の変更が必要ですか?

  たとえば、目標電圧が1.65Vに設定されている場合、目標は、ジッタなしで1.65Vにすばやく到達できることを期待することに他なりません。

  このように、DACのみを使用してデジタル信号を出力する場合、外部エラー(配線、ノイズなど)が最終的な出力値に影響を与える可能性があることを誰もが理解する必要があります。したがって、最終的に何を読み取るためにPID調整を使用する必要があります。価値が欲しい。

ここに画像の説明を挿入
:1.65Vを出力する必要があり、制御出力は1.65Vです。実際に得られるのは1.6Vです。制御出力が1.68Vの場合、1.65Vが得られる可能性があります。実際には、ターゲットと実際の間のエラー。


2. STM32CubeMX構成:

2.1使用したツール:

  • チップ:STM32F103RCT6
  • IDE:MDK-Keilソフトウェア
  • STM32F1xxHALライブラリ

2.2知識の要約:

  • STM32CubeMXは、ADC、DMA、DAC、USARTルーチンを作成します
  • Keilソフトウェアプログラミング

2.3プロジェクトの作成

1.チップセレクト
  チップ:STM32F103RCT6(独自のボードに応じて選択)2。RCC

ここに画像の説明を挿入

  設定して高速外部クロックHSEを設定し、外部クロックソースを選択します

ここに画像の説明を挿入
3. ADCピン
  ADC1チャネル0またはPA0を設定し、連続変換モードを開き、変換サイクル:55.5サイクル

ここに画像の説明を挿入
ここに画像の説明を挿入

4. ADCはDMA送信を使用してDMA送信
  モード設定します:サイクリック送信(データがある場合は送信)、および同時に高優先度
  設定します。5.DAC
ここに画像の説明を挿入
出力を
ここに画像の説明を挿入
オンにします。6。USART1をオンにして
非同期通信設定します。ボーレート115200ビット/ s

ここに画像の説明を挿入

7.クロック
  F1シリーズチップシステムクロックを72MHzに設定し
ます。8
ここに画像の説明を挿入
。プロジェクト作成の最終ステップ

  • プロジェクト名を設定する
  • ストレージパスを設定する
  • IDEを選択してください

ここに画像の説明を挿入

9.出力ファイル

  • ②場所:使用したファイルの.cと.hをコピーします
  • ③Office:各関数は独立した.cファイルと.hファイルを生成します
    ここに画像の説明を挿入

10.プロジェクトファイルを作成し、
  [コードの生成]をクリックしてプロジェクトを作成します

11.ダウンロードツールを構成します。
  ここでは、ダウンロードを確認して直接実行する必要があります。

ここに画像の説明を挿入


3. STM32ソースコード:

  最初にpid.cおよびpid.hファイルコードを記述します。これがpid位置アルゴリズムです。
(1)pid.h

#ifndef __PID_H__
#define __PID_H__
#include "main.h"

typedef struct
{
    
    
    float SetVoltage;	  	//定义设定值
    float ActualVoltage;	//定义实际值
    float err;			    //定义偏差值
    float err_last;		  	//定义上一个偏差值
    float Kp,Ki,Kd;		  	//定义比例、积分、微分系数
    float result;		    //pid计算结果
    float voltage;		  	//定义电压值(控制执行器的变量)0-5v右转 5-10v左转
    float integral;		  	//定义积分值
}pid_p; 

void PID_init( void);
float PID_realize( float v, float v_r);

#endif

(2)pid.c

#include "pid.h"
#include "stdio.h"

pid_p pid;

//pid位置式
void PID_init()
{
    
    
    printf("PID_init begin \n");
    pid.SetVoltage= 0.0;		  	// 设定的预期电压值
    pid.ActualVoltage= 0.0;			// adc实际电压值
    pid.err= 0.0;				    // 当前次实际与理想的偏差
    pid.err_last=0.0;			    // 上一次的偏差
    pid.voltage= 0.0;			    // 控制电压值
    pid.integral= 0.0;			  	// 积分值
    pid.Kp= 0.2;				    // 比例系数
    pid.Ki= 0.15;				    // 积分系数
    pid.Kd= 0.2;				    // 微分系数
    printf("PID_init end \n");
}

float PID_realize( float v, float v_r)
{
    
    
    pid.SetVoltage = v;			// 固定电压值传入
    pid.ActualVoltage = v_r;	// 实际电压传入 = ADC_Value * 3.3f/ 4096
    pid.err = pid.SetVoltage - pid.ActualVoltage;	//计算偏差
    pid.integral += pid.err;						//积分求和
    pid.result = pid.Kp * pid.err + pid.Ki * pid.integral + pid.Kd * ( pid.err - pid.err_last);//位置式公式
    pid.err_last = pid.err;				//留住上一次误差
    return pid.result;
}

(3)main.cを追加します:

/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "pid.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PD */
#define ADC_Channel_MAX 2
/* USER CODE END PD */
/* USER CODE BEGIN PV */
uint16_t ADC_DMA_Value[ADC_Channel_MAX];  // DMA得到ADC的值
uint16_t ADC_Value = 0;
uint16_t DAC_Value = 100;
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
/**
  * 函数功能: 重定向c库函数printf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
    
    
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
    
    
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}
/* USER CODE END 0 */

(4)ADC初期化後にADキャリブレーション機能を追加します。

  /* USER CODE BEGIN 2 */
  HAL_ADCEx_Calibration_Start(&hadc1);  // f1系列需要ADC校准,f4不需要
  HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&ADC_DMA_Value,ADC_Channel_MAX); // 启动ADC的DMA转换
  PID_init();
  /* USER CODE END 2 */

(5)追加するwhile:

      HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, DAC_Value); // 设置DAC数值
	  HAL_DAC_Start(&hdac,DAC_CHANNEL_1);   // 开启DAC输出
	  ADC_Value = ADC_DMA_Value[0];
	  printf("%0.2f\r\n", ADC_Value*3.3/4096);
	  // 这里设置输出1.65V
	  DAC_Value = DAC_Value + PID_realize(2048, ADC_Value);
	  HAL_Delay(100);

(6)PA0(ADC1_IN0)とPA4(DAC)をDuPontケーブルで接続し、シリアルポートをコンピューターに接続します(USBからTLLを使用してコンピューターに接続し、RXをPA9(USART1_TX)に接続し、TXをに接続しますPA10(USART1_RX))

(7)その後、通常の読み取りが完了します。シリアルポートを開いたばかりの場合:
ここに画像の説明を挿入
(8)PID調整が安定した後(DAC出力1.65V):
ここに画像の説明を挿入
プログラムダウンロードアドレス:https//download.csdn.net/ダウンロード/ weixin_44270218 / 13981014

総括する:

  上記は、PID調整制御を使用して、設定したい電圧値を取得するためのものです。

おすすめ

転載: blog.csdn.net/weixin_44270218/article/details/111904403