【工程详解】基于Stm32c8t6-镭射激光打印机的设计工程详解

简介:

         对之前镭射打印机设计做一个详细的设计思路介绍,包括硬件思路和软件思路,包括一部分PWM的原理和实践。

博客介绍:【STM32项目】基于Stm32c8t6-镭射激光打印机的设计(完整工程资料源码)_stm32驱动激光打印机-CSDN博客

视频效果:基于STM32-镭射激光打印机的设计-CSDN直播

工程资料:毕设&大创&立项&;竞赛-基于Stm32c8t6-镭射激光打印机的设计.zip(完整工程资料源码)_stm32驱动激光打印机资源-CSDN文库

目录

一、硬件思路:

二、软件思路:

2.1 Halcon读取像素程序: 

 2.2 stm32程序:

   

2.3  TIM3_PWM_Init(16, 7200);

2.4  TIM2_PWM_Init(16, 7200);

2.5 led_Init()

 三、关于PWM

3.1 pwm简介:

3.2 pwm原理:

3.3 PWM输出呼吸灯:

3.4 PWM对电机转速的控制:

3.5 PWM对舵机的控制:


一、硬件思路:

1.采用stm32f103c8t6作为控制核心,内部有64KB的FLASH,可以存储图片像素信息;

2.用IRFZ44N场效应管作为开关控制镭射激光头,激光头250mw,5V供电。

3.用A4988芯片驱动丝杆电机,可以将单片机的PWM信号转化为步进电机的驱动信号。

二、软件思路:

2.1 Halcon读取像素程序: 

        图像是由一个个很小的像素块组成的

        使用Halcon编写程序读取图像所有像素信息,Halcon是一款工业用计算机视觉软件。基本原理就是读取图像每一个点的像素值,并将其返回到一个数组中。之后对其进行二值化处理,像素高于127的,属于图像中偏白色的点,将其记作0,存入数组中,单片机读取后,激光头运行到这个像素点时不发射激光;反之,像素值低于127的,属于图像中比较黑的部分,激光头运行到这个像素点时发射激光,将奥松板这个点烧黑。

* 读取一张灰度图像
read_image (Image, 'E:/Halcon/素材/33.jpg')  % 读取图像文件

* 获取图像大小
get_image_size(Image, Width, Height)  % 获取图像宽度和高度

dev_close_window ()  % 关闭窗口
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)  % 打开新的窗口

* 获取区域里每个像素的坐标
* 参数2,3:输出参数
get_region_points(Image, Rows, Columns)  % 获取图像区域内的像素坐标

* 获取图像的灰度值
* 参数1,2,3输入参数;参数4:输出参数
get_grayval(Image, Rows, Columns, Grayval)  % 获取图像的灰度值

* 创建一个空的矩阵
* 参数3: 矩阵的初始值; 参数4: 矩阵的句柄
*create_matrix(Height, Width, 0, GrayMatrix)  % 创建一个空矩阵,大小为宽度和高度,初始值为0

* 为矩阵填充图像数据
*set_value_matrix(GrayMatrix, Rows, Columns, Grayval)  % 将灰度值填充到矩阵中

*get_value_matrix (GrayMatrix, 0, 511, Value)  % 从矩阵中获取指定范围内的值并赋值给Value变量

xiangsu:= Width * Height *3  % 根据图像的大小和操作的需要定义一个变量
A[Width * Height]:=0  % 为一个三维数组(即矩阵)的每个元素设置初始值为0,此处主要是为后面逻辑赋值作准备

step := 3  % 为遍历需要设定的步长值,这里是每次三格跨度,例如可以从下一张位置变为下两格的位置时中间的那个点会有输出。根据代码描述可推算出可能这个数对应3步的范围输出或中断等条件判断点。

for i := 1 to xiangsu-2 by step  % 进行循环遍历矩阵数据
    if(Grayval[i]>127)  % 如果灰度值大于127(根据需求可以更改阈值)
        A[(i-1)/step] :=0  % 那么将上一行的元素设为0(代表黑色)
    else
        A[(i-1)/step] :=1  % 否则将上一行的元素设为1(代表白色)
    endif
    *A[(i-1)/step] := Grayval[i]  % 将当前灰度值赋值给上一行的元素,此处可能代表中间像素的值或状态。
endfor  % 结束循环遍历操作

for Index := 1 to xiangsu-1 by 1  % 对每个像素进行处理(这里的代码注释较少,所以理解可能有点困难)
    if (Grayval[Index]==255)  % 如果当前像素是白色(255表示白色)
        A[Index]:=0  % 那么将对应的索引设置为0(可能是空白)
    else  % 如果当前像素是黑色(灰色)或白色以外的其他颜色,设置为黑色,或者是可能是把大于127的部分也视为黑色部分进行忽略或遮盖处理。这个需要具体查看代码才能明确。
        A[Index]:=1  % 其他颜色则设置为黑色。可能这个部分的逻辑有些模糊,可能需要具体查看代码才能理解。
    endif
endfor  % 对每个像素进行处理结束。

 2.2 stm32程序:

接下来就是用keil给单片机编程,把像素信息传给单片机,放入数组中:

         然后编写控制激光头移动的程序,即控制丝杆电机转动。基本思想是:上面的丝杆电机往右移动,直到遍历完一行的像素值,下面的丝杆电机往前移动一点点,上面的电机再遍历下一行的像素值,直到遍历完所有行。程序实现也很简单,2个for的循环语句嵌套一下。遍历时激光头移动到某个位置上方,查询数组中对应的像素值,如果为1 就发射激光,烧黑奥松板的这个点;如果是0就关闭激光。

int main(void) {
    // 定义两个整数变量i和j,并初始化为0
    int i, j = 0;

    // 调用SysTick_Init()函数进行初始化
    // 这个函数的具体实现没有给出,但通常用于配置和初始化系统定时器
    SysTick_Init();

    // 使能总算法时钟
    // 这个操作通常用于启用或设置特定的时钟源,以便系统能够正常运行
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

    // 初始化延时函数
    // 这个函数的具体实现也没有给出,但通常用于设置定时器或延迟执行某些操作
    delay_init();

    // 配置NVIC的优先级分组
    // NVIC是嵌套向量中断控制器,这个函数用于配置中断优先级分组
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    // 初始化TIM3定时器产生PWM信号
    // TIM3可能是一个定时器,用于产生PWM信号,控制某个硬件设备
    TIM3_PWM_Init(16, 7200);

    // 初始化TIM2定时器产生PWM信号
    // TIM2可能也是一个定时器,用于产生PWM信号,控制另一个硬件设备
    TIM2_PWM_Init(16, 7200);

    // 初始化LED灯的驱动函数
    // 这个函数的具体实现也没有给出,但通常用于初始化LED灯驱动电路
    led_Init();

    // 延时等待初始化稳定
    // 这个函数用于延迟一段时间,等待所有初始化操作完成并稳定运行
    delay_ms(1000);

    while (1) { // 无限循环,程序将一直运行下去
        for (i = 1; i < hang; i++) { // 从第1行开始循环执行,直到hang行结束
            if (i % 2 == 1) { // 如果当前行数是奇数(从1开始计数)
                // 上方往右操作,点亮GPIO_Pin_15并设置PA3输出PWM信号
                GPIO_SetBits(GPIOB, GPIO_Pin_15); // 设置GPIOB的第15位为高电平(点亮LED)
                TIM_SetCompare4(TIM2, 8); // 设置TIM2的计数器比较值为8,控制PA3输出PWM信号(通常用于控制硬件设备的开关)
                for (j = 1; j < lie; j++) { // 从第1次循环开始执行,直到lie次循环结束
                    if (A[i * lie - lie + j - 1] == 1) { // 如果对应的A数组元素为真(表示某个条件满足)
                        GPIO_SetBits(GPIOB, GPIO_Pin_13); // 设置GPIOB的第13位为高电平(点亮LED)
                        delay_ms(fangge); // 延迟执行一段时间(这个函数的实现也没有给出)
                    } else { // 如果对应的A数组元素为假(表示某个条件不满足)
                        GPIO_ResetBits(GPIOB, GPIO_Pin_13); // 设置GPIOB的第13位为低电平(熄灭LED)
                        delay_ms(fangge); // 延迟执行一段时间(这个函数的实现也没有给出)
                    }
                } // end for loop in line i-1: j<lie-1
                TIM_SetCompare4(TIM2, 0); // 将TIM2的计数器比较值设置为0,停止PA3输出PWM信号(通常用于关闭硬件设备的开关)
                GPIO_ResetBits(GPIOB, GPIO_Pin_13); // 将GPIOB的第13位设置为低电平(熄灭LED)
            } // end if line i is odd (line i is the first line)
            if (i % 2 == 0) { // 如果当前行数是偶数(从2开始计数)
                // 上方往左操作,熄灭GPIO_Pin_15并设置PA3输出PWM信号
                GPIO_ResetBits(GPIOB, GPIO_Pin_15); // 将GPIOB的第15位设置为低电平(熄灭LED)
                TIM_SetCompare4(TIM2, 8); // 设置TIM2的计数器比较值为8,控制PA3输出PWM信号(通常用于控制硬件设备的开关
								// 使用for循环遍历一个数组或数据结构(A)
						for (j = lie; j > 1; j--) {
								// 检查数组中某个位置的元素是否为1(假设A是一个包含某种条件标志的数组)
								if (A[i * lie - lie + j - 1] == 1) {
										// 如果条件满足,设置GPIOB的第13位为高电平(点亮LED)
										GPIO_SetBits(GPIOB, GPIO_Pin_13);
										// 延迟一段时间(fangge表示延迟的时间,具体实现未给出)
										delay_ms(fangge);
								} else {
										// 如果条件不满足,设置GPIOB的第13位为低电平(熄灭LED)
										GPIO_ResetBits(GPIOB, GPIO_Pin_13);
										// 延迟一段时间(fangge表示延迟的时间,具体实现未给出)
										delay_ms(fangge);
								}
						}
						// 停止PA3输出PWM信号
						TIM_SetCompare4(TIM2, 0); 
						// 将GPIOB的第13位设置为低电平(熄灭LED)
						GPIO_ResetBits(GPIOB, GPIO_Pin_13);

						// 下面的代码块是另一个for循环,用于控制另一个硬件设备(可能是另一个GPIO)
						// 控制PA2输出PWM信号
						GPIO_SetBits(GPIOB, GPIO_Pin_14); // 设置GPIOB的第14位为高电平(点亮另一个LED或启动另一个硬件设备)
						// 设置TIM2的计数器比较值为8,控制PA2输出PWM信号(通常用于控制硬件设备的开关)
						TIM_SetCompare3(TIM2, 8); 
						// 延迟一段时间(fangge表示延迟的时间,具体实现未给出)
						delay_ms(fangge); // 这个函数的具体实现也没有给出,可能是用于延迟的函数
						// 停止PA2输出PWM信号
						TIM_SetCompare3(TIM2, 0); // 将TIM2的计数器比较值设置为0,停止输出PWM信号(通常用于关闭硬件设备的开关)
					}

        }
    }
}

   

具体的设计思路如下:

  1. 初始化变量和外设:定义并初始化整数变量i和j调用SysTick_Init()函数初始化系统定时器使能总算法时钟,初始化延时函数,配置NVIC的优先级分组等
  2. 初始化定时器产生PWM信号:分别调用TIM3_PWM_Init()和TIM2_PWM_Init()函数初始化TIM3和TIM2定时器,以产生PWM信号,控制不同的硬件设备
  3. 初始化LED灯的驱动函数:调用led_Init()函数初始化LED灯的驱动电路。
  4. 延时等待初始化稳定:调用delay_ms()函数延时一段时间,等待所有初始化操作完成并稳定运行。
  5. 进入无限循环:使用while(1)进入一个无限循环,程序将一直运行下去。
  6. 循环控制硬件设备:使用for循环遍历行数,从第1行开始循环执行,直到指定的行数结束。
  7. 根据奇偶行数进行不同操作:
    • 如果行数是奇数上方往右操作,点亮GPIO_Pin_15并设置PA3输出PWM信号。然后使用另一个for循环遍历列数,根据A数组的元素值来控制GPIO_Pin_13的亮灭和延时。
    • 如果行数是偶数,上方往左操作,熄灭GPIO_Pin_15并设置PA3输出PWM信号。然后使用另一个for循环遍历列数,根据A数组的元素值来控制GPIO_Pin_13的亮灭和延时。然后再控制另一个硬件设备,控制PA2输出PWM信号。

2.3  TIM3_PWM_Init(16, 7200);

  1. 使能定时器和GPIO时钟:首先,代码通过调用RCC_APB1PeriphClockCmdRCC_APB2PeriphClockCmd函数,分别使能了TIM3定时器和GPIOB端口的时钟。这是使用这些硬件资源前的必要步骤。

  2. 配置GPIO引脚:由于TIM3的某些功能引脚可能与其他功能(如JTAG、USART1)共用,代码首先通过GPIO_PinRemapConfig禁用了USART1引脚的重映射,并禁用了JTAG,以释放相关的GPIO引脚。然后,将GPIOB的第0脚(GPIO_Pin_0)配置为复用推挽输出模式,这是生成PWM信号所必需的配置。

  3. 定时器基础配置:接下来,通过TIM_TimeBaseInit函数配置TIM3的基本参数,包括PWM信号的周期(由arr参数指定)和预分频值(由psc参数指定),以及计数器的计数模式(这里使用向上计数模式)。

  4. PWM模式配置:通过TIM_OCInitStructure结构体和TIM_OC3Init函数,将TIM3的第三个输出通道(OC3)配置为PWM模式2,并设置输出状态为使能以及输出极性为低。这些设置决定了PWM信号的具体行为,如何在计数值与比较值匹配时改变输出。

  5. 使能预装载寄存器:通过TIM_OC3PreloadConfig函数使能预装载寄存器,这允许在下一个更新事件(如计数器溢出)时自动加载新的配置值,而不是立即更改,从而使PWM输出更加平滑。

  6. 启动PWM输出最后,通过TIM_Cmd函数使能TIM3,开始PWM信号的输出。

void TIM3_PWM_Init(u16 arr,u16 psc)
{  
    // 定义GPIO和定时器相关结构体。
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    
    // 使能定时器3时钟。
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    // 配置引脚重映射,这里禁用了USART1引脚的重映射,并禁用了JTAG以释放相关的GPIO。
    GPIO_PinRemapConfig(GPIO_Remap_USART1, DISABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

    // 使能GPIOB端口和AFIO时钟。
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // 设置GPIOB.0为复用推挽输出模式,用于输出TIM3的CH2的PWM信号。
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 初始化定时器3的基础设置。
    TIM_TimeBaseStructure.TIM_Period = arr; // 自动重装载寄存器周期的值。
    TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频值。
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 时钟分割。
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式。
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    // 初始化TIM3的PWM模式。
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // PWM模式2。
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 比较输出使能。
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // 输出极性低。
    TIM_OC3Init(TIM3, &TIM_OCInitStructure); // 初始化TIM3的OC3。

    // 使能预装载寄存器。
    TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);

    // 使能定时器3。
    TIM_Cmd(TIM3, ENABLE);
}

2.4  TIM2_PWM_Init(16, 7200);

  1. GPIO配置:首先,配置相关的GPIO引脚以便它们能够作为TIM2的PWM输出。这包括禁用JTAG功能以释放相关引脚,使能GPIOA和TIM2的时钟,然后将GPIOA的PIN0, PIN1, PIN2, PIN3设置为复用推挽输出模式,这些引脚将用于输出PWM信号。

  2. 定时器基本配置:接着,配置TIM2的基本参数,包括设置PWM信号的周期(通过arr参数,即自动重装载寄存器的值),设置预分频值(通过psc参数,用来降低TIM2的时钟频率),选择时钟分割和计数模式(这里使用向上计数模式)。

  3. PWM模式配置:然后,对TIM2的四个通道分别进行PWM模式配置。这里使用的是PWM模式2,通过设置TIM_OCInitStructure结构体的参数(包括输出状态使能、输出极性为低等),并将这些参数应用到TIM2的四个通道上,实现PWM输出。

  4. 预装载寄存器配置:为了使PWM输出更加平滑,对每个通道启用预装载寄存器,这允许在下一个更新事件(如计数器溢出)时自动加载新的配置值,而不是立即更改,从而避免了PWM输出的潜在抖动。

  5. 启动PWM输出最后,通过使能TIM2,开始PWM输出。

通过这个过程,STM32的TIM2定时器被配置为生成四路独立的PWM信号,这些信号可以用于多种应用,如电机控制、LED调光等。用户可以通过调整arrpsc的值来改变PWM的频率和占空比,以满足不同的应用需求。

void TIM2_PWM_Init(u16 arr,u16 psc)
{  
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    
    // 重新映射USART1和禁用JTAG功能,使能SWD调试
    GPIO_PinRemapConfig(GPIO_Remap_USART1, DISABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); // 禁用JTAG

    // 使能TIM2和GPIOA的时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能TIM2时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  // 使能GPIOA时钟

    // 设置GPIOA的PIN0, PIN1, PIN2, PIN3为复用推挽输出,用于TIM2的PWM输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; // 配置TIM2的四个通道
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  // 设置为复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA

    // 初始化TIM2时间基准
    TIM_TimeBaseStructure.TIM_Period = arr; // 自动重装载寄存器的周期值
    TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 时钟分割
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 初始化TIM2

    // 初始化TIM2的四个通道为PWM模式2
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // PWM模式2
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 比较输出使能
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // 输出极性为低
    // 初始化TIM2的四个通道
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);  // 通道1
    TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);  // 使能预装载寄存器

    TIM_OC2Init(TIM2, &TIM_OCInitStructure);  // 通道2
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);

    TIM_OC3Init(TIM2, &TIM_OCInitStructure);  // 通道3
    TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);

    TIM_OC4Init(TIM2, &TIM_OCInitStructure);  // 通道4
    TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);

    TIM_Cmd(TIM2, ENABLE);  // 使能TIM2
}

2.5 led_Init()

  1. 禁用JTAG功能:通过调用GPIO_PinRemapConfig函数,禁用了JTAG功能,以释放相关的GPIO引脚。这是因为在某些情况下,JTAG功能可能会占用一些GPIO引脚,而我们希望将这些引脚用于LED的控制。

  2. 使能GPIO时钟:通过调用RCC_APB2PeriphClockCmd函数,使能了GPIOB端口的时钟。这是使用这些GPIO引脚前的必要步骤。

  3. 配置GPIO引脚:使用GPIO_InitStructure结构体来配置GPIO引脚的相关参数。在这段代码中,将GPIOB的引脚5、13、14和15配置为输出模式(GPIO_Mode_Out_PP),并设置IO口速度为50MHz。

  4. 初始化GPIO:通过调用GPIO_Init函数,根据设置的参数初始化GPIOB的引脚5、13、14和15。

void led_Init()
{
  GPIO_InitTypeDef  GPIO_InitStructure;
 	GPIO_PinRemapConfig(GPIO_Remap_USART1, DISABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//禁用JTAG
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PA端口时钟

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_13|GPIO_Pin_15|GPIO_Pin_14;				
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 // OUTPUT
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.5
}

 三、关于PWM

3.1 pwm简介:

脉冲宽度调制(PWM)是一种通过调整有效电平(高电平)的持续时间或宽度来控制模拟信号电平的方法。在PWM信号中,频率定义了信号周期的重复速度,而占空比(脉冲宽度与周期的比率)决定了在一个周期内信号为高电平的时间比例。PWM的关键参数包括:

  • 频率(Frequency):PWM信号完整周期的重复次数,单位是赫兹(Hz)。频率决定了PWM信号的周期长度,即从一个高电平开始到下一个高电平开始的时间。例如,50Hz的频率意味着每秒有50个周期,每个周期的长度是20毫秒(1秒/50)。

  • 周期 (T): 是PWM信号完成一次高电平加低电平的总时间。周期的计算公式是 ( T = \frac{1}{f} ),其中 ( f ) 是频率。

  • 占空比(Duty Cycle)在一个周期内,信号为高电平的时间占整个周期时间的百分比。占空比可以用来控制输出信号的平均电压,因此在许多应用中用来控制电机速度、灯光亮度等。

  • 脉宽时间: 是信号在一个周期内保持高电平的时间

        PWM技术的优势在于能够通过数字控制信号来实现对模拟输出的精确控制同时保持能源效率。这种方法不仅用于控制电机速度和LED灯光亮度,还广泛应用于各种电子调速器、电源管理和转换系统中。

        通过改变PWM信号的频率和占空比,可以实现对连接在PWM输出上的设备的精细控制。例如,增加占空比会使得电机转得更快或LED灯更亮,而增加频率可能会影响系统的响应速度和效率。

例如:

  • 总周期时间为10ms。
  • 高电平时间(脉宽时间)为8ms。
  • 从而低电平时间为 ( 10ms - 8ms = 2ms )。
  • 占空比计算为 ( 脉宽时间/周期时间 = 8ms/10ms= 0.8 ) 或 80%。 

        这意味着在这个周期中,信号大部分时间是高电平,只有很小一部分时间是低电平。通过调整占空比,可以控制连接到PWM信号的设备(如电机、LED灯等)的行为。例如,一个电机的速度通常会随着占空比的增加而增加。

3.2 pwm原理:

        PWM(脉冲宽度调制)是一种通过数字信号来模拟模拟电压的技术。在PWM中,我们通过改变高电平(通常是电源电压,如5V)和低电平(通常是0V)的时间比例来模拟不同的电压水平。

让我们更详细地解释一下:

  • 高电平 (High): 通常是单片机的供电电压,例如5V。
  • 低电平 (Low): 通常是0V。
  • 占空比 (Duty Cycle): 是高电平时间与整个周期时间的比例。例如,50%的占空比意味着高电平和低电平各占一半的时间。

在PWM中,我们通过改变占空比来模拟不同的电压。例如:

  • 当占空比为50%时,平均电压是电源电压的一半,即2.5V。这是因为在一半的时间里,电压是5V,而在另一半的时间里,电压是0V。因此,平均电压是 ( 5V/2 = 2.5V )。
  • 当占空比为75%时,平均电压是电源电压的75%,即3.75V。这是因为75%的时间里,电压是5V,而在剩下的25%的时间里,电压是0V。因此,平均电压是 ( 5V*0.75 = 3.75V )。

        这种技术对于控制LED亮度、电机速度等非常有用,因为它允许我们使用数字信号来精确地控制模拟设备。需要注意的是,PWM的频率也很重要,因为它决定了输出电压的平滑程度。如果频率太低,输出电压可能会有明显的脉动,这可能会影响设备的性能。通常,PWM频率的选择取决于应用的具体要求。

        如果需要在单片机上实现PWM输出,需要查阅该单片机的数据手册,了解如何配置定时器/计数器来生成PWM信号。大多数现代单片机都内置了PWM功能,可以通过编程来设置频率和占空比。

        PWM(脉冲宽度调制)通过改变脉冲的占空比来实现数字信号到模拟信号的转换,这在本质上是一种数字到模拟转换(D/A转换)的方法。PWM通过改变数字信号的占空比来模拟不同的模拟电压水平,从而实现了数字到模拟的转换。这种技术在电子工程中非常常见,尤其是在需要精确控制模拟设备(如电机、加热器、LED等)的应用中。通过编程控制单片机或其他数字控制器的输出,可以轻松实现PWM信号的生成和调节。

3.3 PWM输出呼吸灯:

        人眼的视觉暂留效应使得我们能够感知到连续的图像,即使这些图像实际上是以一定的频率快速切换的。对于LED灯来说,这个原理同样适用。

  1. 视觉暂留效应: 人眼的视觉暂留时间大约是10到40毫秒。这意味着,如果LED灯的开关频率高于这个时间范围,人眼就会将快速切换的亮灭状态感知为一个连续的亮度,而不是闪烁。

  2. 闪烁感: 当LED灯的开关频率低于人眼的闪烁融合频率(通常认为大约是50Hz到60Hz),人眼就会感知到闪烁。例如,如果LED灯以1Hz的频率开关(即每秒开关一次),那么人眼会明显感觉到灯在闪烁。

  3. 亮度控制: 当LED灯的开关频率足够高(通常认为高于80Hz到100Hz),人眼就不会感知到闪烁,而是感知到一个稳定的亮度。在这种情况下,通过改变PWM信号的占空比,可以控制LED灯的亮度。占空比越大,LED灯的平均亮度越高;占空比越小,LED灯的平均亮度越低。

  4. 呼吸灯效果: 通过逐渐改变PWM信号的占空比,可以实现LED灯的亮度逐渐增加和减少,从而创造出一种类似于呼吸的效果。这种效果在许多现代电子设备中被用来提供视觉反馈,例如智能手机的通知指示灯。

        通过使用PWM技术,可以在不改变LED灯的物理特性(如电流或电压)的情况下,通过改变占空比来精确控制LED灯的亮度。这种方法在需要动态亮度调节的应用中非常有用,如汽车照明、家庭照明、电子显示设备等。

3.4 PWM对电机转速的控制:

        PWM(脉宽调制)技术在电机控制中被广泛应用,特别是在直流电机和无刷直流电机的速度控制中。

  1. 电机速度控制: 通过PWM信号,可以控制电机两端的平均电压,从而控制电机的转速。当PWM信号的占空比增加时,电机两端的平均电压增加,电机的转速也随之增加。反之,当占空比减小时,电机的转速降低。

  2. 电机响应: 电机由于其电感特性,不会立即响应电压的变化。当PWM信号从高电平切换到低电平时,电机不会立即停止,而是会因为电感的储能作用继续转动。这种特性使得电机能够在PWM信号的周期内保持一个相对稳定的转速。

  3. 频率选择: 在电机控制中,PWM信号的频率选择非常重要。频率太低会导致电机转速不稳定,并且可能会产生人耳可听的噪声。频率太高则可能导致电机无法及时响应,因为电机和驱动电路都有一定的响应时间。通常,电机控制的PWM频率选择在几千赫兹到十几千赫兹之间,这样可以确保电机有足够的响应时间,同时避免产生噪声。

  4. 电机类型: 不同类型的电机对PWM频率的适应性不同。例如,无刷直流电机(BLDC)和永磁同步电机(PMSM)通常需要更高的PWM频率,因为它们通常使用电子换向技术。而传统的直流电机可能对较低的PWM频率更为适应。

  5. 电机保护: 在使用PWM控制电机时,还需要考虑电机的保护。由于PWM信号会导致电机两端的电压快速切换,这可能会引起电机内部的电磁干扰和热量积累。因此,设计电机控制系统时,需要考虑适当的滤波和散热措施。

        PWM技术是一种非常有效的电机速度控制方法,它通过改变电机两端的平均电压来实现对电机转速的精确控制。在实际应用中,需要根据电机的类型和应用场景来选择合适的PWM频率和占空比,以确保电机的稳定运行和最佳性能。

3.5 PWM对舵机的控制:

        舵机(Servo motor)是一种特殊类型的电机,可以精确控制角度、速度和加速度。舵机通常用在遥控玩具、模型飞机、机器人以及任何需要精确角度控制的场合。

        传统的模拟伺服机通常使用50Hz的脉冲宽度调制(PWM)信号来控制其位置。在这个频率下,每个周期大约为20ms。在这20ms周期内,高电平的持续时间(脉宽)将决定舵机臂的角度。一个0.5ms至2.5ms的脉宽范围通常对应于0至180度的运动范围。不同的舵机可能对特定脉宽的响应稍有差异,但大致上,这个范围是标准的。

  • 0.5ms的脉宽让舵机转到它的最小角度,通常是0度。
  • 2.5ms的脉宽则让舵机转到它的最大角度,通常是180度。
  • 当脉宽为1.5ms时,舵机通常会定位在中间位置,也就是90度。

        这种类型的舵机控制非常普遍,因为PWM信号生成简单,而且大多数微控制器都有产生PWM信号的内置硬件和库支持。在设计和应用舵机系统时,了解舵机的脉宽-角度关系对于实现预期的动作至关重要。此外,编程时需要确保微控制器输出的PWM信号精确,因为即使很小的脉宽差异也可能导致舵机转动到错误的位置。

 

最近更新

  1. TCP协议是安全的吗?

    2024-05-09 20:02:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-09 20:02:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-09 20:02:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-09 20:02:04       20 阅读

热门阅读

  1. Springboot整合Minio,2024版教程

    2024-05-09 20:02:04       11 阅读
  2. 【android systrace学习】

    2024-05-09 20:02:04       11 阅读
  3. MySQL中SELECT语句的执行流程详解

    2024-05-09 20:02:04       10 阅读
  4. BL120协议Modbus RTU和Modbus TCP互转

    2024-05-09 20:02:04       11 阅读
  5. mybatis 批量添加数据

    2024-05-09 20:02:04       8 阅读
  6. Utreexod:支持Utreexo累加器的比特币全节点

    2024-05-09 20:02:04       12 阅读
  7. 解决报错HTTPError: HTTP Error 403: Forbidden

    2024-05-09 20:02:04       11 阅读
  8. TypeScript基础:类型系统介绍

    2024-05-09 20:02:04       11 阅读
  9. 20个硬核Python脚本

    2024-05-09 20:02:04       8 阅读
  10. 《深入理解kafka》对于实际问题的理解

    2024-05-09 20:02:04       12 阅读