电赛 | 电源题软件如何准备?
关注、星标公众号,直达精彩内容
摘要:PWM和SPWM在电源的备战中是很有必要的。基础的恒流源、恒压源需要使用PWM的占空比及频率来达到数控的作用,往后的逆变则需要用到SPWM。当然还有ADC、DAC、IIC、SPI、算法。
一、PWM/SPWM
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调试。是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。广泛应用在从测量、通信到功率控制与变换的许多领域中。
SPWM(Sinusoidal PWM) 法是一种比较成熟的、使用较广泛的PWM法。冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同。SPWM法就是以该结论为理论基础,用脉冲宽度按正弦规律变化而和正弦波等效的PWM波形即SPWM波形控制逆变电路中开关器件的通断,使其输出的脉冲电压的面积与所希望输出的正弦波在相应区间内的面积相等,通过改变调制波的频率和幅值则可调节逆变电路输出电压的频率和幅值。
1、CubeMX相关配置-PWM
使能PWM通道
在这里我将TIM2的Channel1设置为PWM输出通道(PWM Generation CHx 正向、PWM Generation CHxN 反向、PWM Generation CHx CHxN一对互补pwm输出)
配置频率及占空比
频率 = 定时器时钟 / (Prescaler 预分频 + 1)/ (Counter Period 计数值 + 1)Hz
占空比 = Pulse ( 对比值) / (C ounter Period 计数值)%
2、编写业务代码-PWM
// 使能timx的通道y
HAL_TIM_PWM_Start(&htimx,TIM_CHANNEL_y);
// 修改timx的通道y的pwm比较值为z,即修改占空比
__HAL_TIM_SET_COMPARE(&htimx, TIM_CHANNEL_y, z);
pwm 的输出是很简单的,但是因为定时器的频率是有上限的通常需要在频率和pwm
的精细度两者之间做取舍。所以你想做电源,那么你可以了解一下STM32F334
这款处理器,它拥有一个高分辨率定时器 (HRTIM),能将定时器的频率倍频至4.096G
。那你在频率和pwm
的精细度两者都可以兼得。
SPWM 其实就是在 PWM 的基础上,让 PWM 的占空比做正弦变化。
3、CubeMX相关配置-SPWM
之前的 PWM 生成的操作不变,只需要开启一个新的定时器,配置完后需要开启定时器中断
4、使用软件生成正弦向量表-SPWM
SPWM 中值 = Pulse ( 对比值) /2SPWM 幅值 = Pulse ( 对比值) /2
周内点数影响频率与正弦波精细度。周内点数越大,频率越小、正弦波精细度越高。
5、编写业务代码-SPWM
uint16_t sin[] =
{1800,1913,2025,2137,2247,2356,2462,2566,2667,2764,2858,2947,3032,3112,3186,3256,3319,3377,3428,3473,3511,3543,3568,3585,3596,3600,3596,3585,3568,3543,3511,3473,3428,3377,3319,3256,3186,3112,3032,2947,2858,2764,2667,2566,2462,2356,2247,2137,2025,1913,1800,1686,1574,1462,1352,1243,1137,1033,932,835,741,652,567,487,413,343,280,222,171,126,88,56,31,14,3,0,3,14,31,56,88,126,171,222,280,343,413,487,567,652,741,835,932,1033,1137,1243,1352,1462,1574,1686
}
int main()
{HAL_TIM_PWM_Start(&htimx,TIM_CHANNEL_y); // 开启pwm输出HAL_TIM_Base_Start_IT(&htimz); //使能刚刚配置的定时器zwhile(1){}
}
/**
* @brief 定时器中断的回调函数
* @param htim 触发中断的定时器
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{static int i = 0;if(++i == size)i = 0;if (htim->Instance == htim3.Instance){__HAL_TIM_SET_COMPARE(&htimx, TIM_CHANNEL_y, sin[i]); //由向量表修改占空比}
}
二、ADC/SDADC/ADS
先介绍最简单的片上 ADC,通常是 12 位,精度则为 3.3/4096 v。读取 ADC 的方式有很多:
1、轮询
2、中断
3、DMA
因为在实际开发中仅有轮询和 DMA 存在使用场景,所以在这里我仅介绍轮询和DMA 的方式。
1、CubeMX相关配置-轮询方式
2、编写业务代码-轮询方式
while(1)
{HAL_ADC_Start(&hadc1);//启动ADC装换HAL_ADC_PollForConversion(&hadc1, 50);//等待转换完成,第二个参数表示超时时间,单位ms.if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC)){AD_Value = HAL_ADC_GetValue(&hadc1);//读取ADC转换数据,数据为12位printf("[\tmain]info:v=%.1fmv\r\n",AD_Value*3300.0/4096);//打印日志}
}
前面介绍了通过 ADC 轮询的方式采集单通道的数据。现在介绍一下通过 DMA 方式采集多通道的数据。
3、CubeMX相关配置-DMA方式
3.1初始化两个ADC通道
3.2、配置相关属性
使能扫描转换模式 (Scan Conversion Mode), 使能连续转换模式 (Continuous Conversion Mode)。
ADC 规则组选择转换通道数为 2(Number Of Conversion)。
配置 Rank 的输入通道。
3.3、添加 DMA
添加DMA设置,设置为连续传输模式,数据长度为字。
4、编写业务代码-DMA 方式
1、在main 函数前面添加变量。其中 ADC_Value 作为转换数据缓存数组,ad1,ad2 存储PA0(转换通道 0),PA1(转换通道1) 的电压值。
/* USER CODE BEGIN PV */
/* Private variables */
uint32_t ADC_Value[100];
uint8_t i;
uint32_t ad1,ad2;
/* USER CODE END PV */
2、在 while(1) 前面以 DMA 方式开启 ADC 装换。HAL_ADC_Start_DMA()
函数第二个参数为数据存储起始地址,第三个参数为 DMA 传输数据的长度。
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 100);
/* USER CODE END 2 */
由于DMA
采用了连续传输的模式,ADC
采集到的数据会不断传到到存储器中(此处即为数组 ADC_Value
)。ADC
采集的数据从 ADC_Value[0]
一直存储到 ADC_Value[99]
,然后采集到的数据又重新存储到ADC_Value[0]
,一直到ADC_Value[99]
。所以ADC_Value
数组里面的数据会不断被刷新。
这个过程中是通过DMA
控制的,不需要CPU
参与。我们只需读取ADC_Value
里面的数据即可得到 ADC 采集到的数据。其中ADC_Value[0]
为通道 0(PA0) 采集的数据,ADC_Value[1]
为通道 1(PA1) 采集的数据,ADC_Value[2]
为通道 0 采集的数据,如此类推。数组偶数下标的数据为通道 0 采集数据,数组奇数下标的数据为通道1采集数据。
在while(1) 循环中添加应用程序,将采集的数据装换为电压值并输出。
/* USER CODE BEGIN WHILE */
while (1)
{/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_Delay(500);for(i = 0,ad1 =0,ad2=0; i < 100;){ad1 += ADC_Value[i++];ad2 += ADC_Value[i++];}ad1 /= 50;ad2 /= 50;printf("\r\n********ADC-DMA-Example********\r\n");printf("[\tmain]info:AD1_value=%1.3fV\r\n", ad1*3.3f/4096);printf("[\tmain]info:AD2_value=%1.3fV\r\n", ad2*3.3f/4096);
}
/* USER CODE END 3 */
程序中将数组偶数下标数据加起来求平均值,实现均值滤波的功能,再将数据装换为电压值,即为PA0管脚的电压值。同理对数组奇数下标数据处理得到PA1管脚的电压值。
同时ADC采样也可以采用我之前描述的采用定时器对其平滑滤波!
通常片上的ADC的精度往往达不到我们的要求,因为它的精度实在是太低了。有两个替代方案:
1、SDADC, 这个是STM32F373
上特有的功能,16位高速ADC,支持差分输入。掌握难度较大,我也没有很好的掌握,所以就不在此展示了。
2、ADS, 就是外置 ADC。在我们比赛前,我们一直调教的是 ADS1256 这款芯片,能做到 0.01mV 的精度!这类芯片只需要进行 SPI 通信操作,便可以获取 ADC 数据。
三、DAC数模转化
说实话,这两年的开发中,我还没有使用过 DAC 的功能。但是这个功能也十分简单,配置好引脚后,编写业务代码即可。
1、CubeMX相关配置
勾选DAC
中的OUT Configuration
, 其余配置为默认配置不需修改。
2、编写业务代码
//开启DAC转换
HAL_DAC_Start(&hdac, DAC_CHANNEL_2);
// 设置DAC的大小
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, 2048);
编译程序并下载到开发板。如果没有出错用万用表测管脚的电压为1.65V。
四、I2C/SPI
在开发中,使用到 I2C/SPI 的时候通常是与其他模块间的通信,例如:使用I2C与OLED
通信,使用 SPI 与ADS1256
通信。所以在此情况下,我们只需要在模块现有库函数的基础之上,做少量代码的移植即可。
1、CubeMX相关配置-I2C
直接使能 I2C 即可。
2、编写业务代码-I2C
//主机的发送
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
//主机的接收
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
//从机的发送
HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t * pData, uint16_t Size, uint32_t Timeout);
//从机的接收
HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
3、OLED 的移植-I2C
3.1、原有库函数的代码
...
void I2C_Configuration(void)
{I2C_InitTypeDef I2C_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_Init(GPIOB, &GPIO_InitStructure);I2C_DeInit(I2C1);I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;I2C_InitStructure.I2C_OwnAddress1 = 0x30;I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStructure.I2C_ClockSpeed = 400000;I2C_Cmd(I2C1, ENABLE);I2C_Init(I2C1, &I2C_InitStructure);
}
void I2C_WriteByte(uint8_t addr,uint8_t data)
{while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));I2C_GenerateSTART(I2C1, ENABLE);while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));I2C_SendData(I2C1, addr);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));I2C_SendData(I2C1, data);while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));I2C_GenerateSTOP(I2C1, ENABLE);
}
void WriteCmd(unsigned char I2C_Command)
{I2C_WriteByte(0x00, I2C_Command);
}
void WriteDat(unsigned char I2C_Data)
{I2C_WriteByte(0x40, I2C_Data);
}
void OLED_Init(void)
{DelayMs(100);
...
3.2、移植代码分析
I2C_Configuration
其实就是I2C的初始化函数,CubeMX会帮我们生成,所以直接删除
I2C_WriteByte
被接下来的两个函数依赖,但是HAL中有相应的函数,所以直接删除
WriteCmd
和WriteDat
改写成HAL库的方式
DelayMs
改为 HAL 库中的函数
3.3、移植后的代码
...
#include "i2c.h"
void WriteCmd(unsigned char I2C_Command)
{HAL_I2C_Mem_Write(&hi2c1,OLED_ADDRESS,0x00,I2C_MEMADD_SIZE_8BIT,&I2C_Command,1,100);
}
void WriteDat(unsigned char I2C_Data)
{HAL_I2C_Mem_Write(&hi2c1,OLED_ADDRESS,0x40,I2C_MEMADD_SIZE_8BIT,&I2C_Data,1,100);
}
void OLED_Init(void)
{HAL_Delay(100);
...
4、CubeMX相关配置-SPI
使能SPI后,但是需要根据设备的不同做分频处理。
5、编写业务代码-SPI
//SPI的发送
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData,uint16_t Size, uint32_t Timeout);
//SPI的接收
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData,uint16_t Size, uint32_t Timeout);
//SPI的发送和接收
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,
uint32_t Timeout);
6、ADS1256 的移植-SPI
SPI的移植比I2C的移植要难并且复杂很多,基本上所有的函数都需要做大大小小的改动,建议大家尽量不要自己移植,最好是在网上找到相关的资源。
五、FLASH
FLASH 的操作,不需要使用Cube MX做任何的配置,只需要做编程操作即可。
1、相关定义
#define BaseAddress ((uint32_t)0x080E0000) // 操作FLAH基地址
//需根据自己单片机的型号进行修改
uint32_t paper_table[100] = {0} ;//需要写入FLAH中的第一张表
uint32_t pwm_table[100] = {0};//需要写入FLAH中的第二张表
uint32_t length_table = 0;
2、FLAH 的写入
注意:我接下来提供的例程是来自STM32F407
,不同板子间的FLASH_EraseInitTypeDef
可能不同。
HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef f;
f.TypeErase = FLASH_TYPEERASE_SECTORS;
//F103中为FLASH_TYPEERASE_PAGES,即页擦除
f.Sector = FLASH_SECTOR_11;
//F103中为 f.PageAddress = BaseAddress 即开始操作的地址为BaseAddress
f.NbSectors = 1;
//F103中为 f.NbPages = x,即擦除x页
//设置PageError
uint32_t PageError = 0;
//调用擦除函数
HAL_FLASHEx_Erase(&f, &PageError);
//对FLASH烧写
for(int i = 0; i < 100; i++)
{HAL_FLASH_Program(TYPEPROGRAM_WORD, (BaseAddress + 4 * i), paper_table[i]);
}
for(int i = 0; i < 100; i++)
{HAL_FLASH_Program(TYPEPROGRAM_WORD, (BaseAddress + 400 + 4 * i), pwm_table[i]);
}
//锁住FLASH
HAL_FLASH_Lock();
3、FLAH 的读取
FLAH
的读取十分简单,只需要读取相应地址上的值即可。
for(int i = 0; i < 100; i++)
{paper_table[i] = *(__IO uint32_t*) (BaseAddress + 4 * i);
}
for(int i = 0; i < 100; i++)
{pwm_table[i] = *(__IO uint32_t*) (BaseAddress + 400 + 4 * i);
}
while(paper_table[length_table] != 0)
{length_table++;
}
六、算法-排序
这两个模板,是我用了很久的,通过长时间的测试,我向你保证它是绝对的可靠!
1、快速排序
void quick_sort(int q[], int l, int r)
{if (l >= r) return;int i = l - 1, j = r + 1, x = q[l];while (i < j){do i ++ ; while (q[i] < x);do j -- ; while (q[j] > x);if (i < j) {q[i] = q[i]^q[j];q[j] = q[i]^q[j];q[i] = q[i]^q[j];
}
else break;
}quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
2、归并排序
void merge_sort(int q[], int l, int r)
{if (l >= r) return;int mid = l + r >> 1;merge_sort(q, l, mid);merge_sort(q, mid + 1, r);int k = 0, i = l, j = mid + 1;while (i <= mid && j <= r)if (q[i] < q[j]) tmp[k ++ ] = q[i ++ ];else tmp[k ++ ] = q[j ++ ];while (i <= mid) tmp[k ++ ] = q[i ++ ];while (j <= r) tmp[k ++ ] = q[j ++ ];for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
3、算法-MPPT
在做最大功率点追踪,这个算法是十分重要的。我在这里分享一下我是怎么对其优化的,首先我写了一个能实现功能的最基础的版本。
4、基础版本
#include "mppt.h"
#include "main.h"
#include "usart.h"
//上一次的功率
double l_power = 0.0 ;
//功率上升或下降
int updown = 0;
//步长
int MPPT_STEP = 160;
/* 扰动法计算
*
*/
int mppt_po(double u, double i, int pwm)
{double power = (u * i) < 0 ? 0 : u * i ;printf("[Info]mppt_po:当前电流:%f,当前电压:%f,当前功率:%f\r\n", i, u, power);if(power < l_power || power == 0) {updown ^= 1;printf("[Info]mppt_po:当前功率:%f,小于此前功率:%f\r\n", power, l_power);}if(updown) {printf("[Info]mppt_po:PWM:%d调节为:%d\r\n", pwm, pwm + MPPT_STEP);pwm += MPPT_STEP;}else {printf("[Info]mppt_po:PWM:%d调节为:%d\r\n", pwm, pwm - MPPT_STEP);pwm -= MPPT_STEP;}printf("[Info]mppt_po:该次调节结束\r\n");pwm = pwm < 0 ? 0 : (pwm >= 1599 ? 1599 : pwm);l_power = power;return pwm;
}
5、算法的不足与解决方案
1、这个算法一直在调节,这很有可能造成能量的损耗。解决方案:采用标志位,判断是否稳定。
2、这个算法步长不变,从头到尾固定步长。如果步长太长不精细,如果步长太短整体调节较慢。解决方案:采用可变步长。
3、使用三目运算符取代大量的if-else
4、Log信息采用条件编译的方法(很早之前写的,没能采用串口的终极解决方案,有点遗憾)
5、抽离变量,写出结构体,配以初始化函数。
6、最终版本
/**
* @file :mppt.c
*
* @brief: MPPT 最大功率点追踪
*
* @auther : Reyunn
*
*/
#include "mppt.h"
#include "main.h"
#include "usart.h"
extern void quick_sort(int q[], int l, int r);
typedef struct
{double l_power;//上一次的功率uint8_t updown;//功率上升或下降int max_step;//步长int min_step;//步长int pwm_max ; //pwm最大值int pwm_min ; //pwm最小值uint8_t count; //计算微调次数uint8_t state; //状态uint8_t time; //改变方向次数int l_pwm[10];
} MPPT;MPPT mppt;
/**
* @brief mppt 初始化
* @param l_power : 上次测量功率
* @param updown : 上升或下降
* @param min_step :最小步长
* @param max_step :最大步长
* @param pwm_max : pwm最大值
* @param pwm_min : pwm最小值
* @retval None
*/
void mppt_init(double l_power, uint8_t updown, int min_step, int max_step, int
pwm_max, int pwm_min)
{mppt.l_power = l_power;mppt.updown = updown;mppt.max_step = max_step;mppt.min_step = min_step;mppt.pwm_max = pwm_max;mppt.pwm_min = pwm_min;mppt.count = 0;mppt.state = 1;mppt.time = 0;
}
/**
* @brief 扰动法计算
* @param u : 当前电压值
* @param i :当前电流值
* @param pwm : 当前pwm值
* * @retval 计算后的pwm值
*/
int mppt_po(double u, double i, int pwm)
{double power = (u * i) < 0 ? 0 : u * i ;if(mppt.state) {#if Logprintf("[info]mppt_po:当前电流:%f,当前电压:%f,当前功率%f\r\n", i, u, power);#endifif(power < mppt.l_power || pwm == mppt.pwm_max || pwm == mppt.pwm_min) {mppt.updown ^= 1;mppt.time ++;if(mppt.time > 5 && power < mppt.l_power ) mppt.l_pwm[mppt.count++] = pwm;#if Logprintf("[info]mppt_po:当前功率:%f,小于此前功率%f\r\n", power, mppt.l_power);#endif}pwm = (mppt.updown == 1) ? ((mppt.count > 0) ? pwm + mppt.min_step : pwm +mppt.max_step) : ( (mppt.count > 0 ) ? pwm - mppt.min_step : pwm - mppt.max_step);pwm = (pwm < mppt.pwm_min ) ? mppt.pwm_min : ( (pwm >= mppt.pwm_max) ? mppt.pwm_max : pwm);mppt.l_power = power;if(mppt.count == 10) {mppt.state = 0;quick_sort(mppt.l_pwm, 0, 9);return ( mppt.l_pwm[5] + mppt.l_pwm[4] + mppt.l_pwm[3] + mppt.l_pwm[6] ) /4;}return pwm;} else {if( power - mppt.l_power > 1000 || power - mppt.l_power < -1000 ){mppt.count = 0;mppt.state = 1;mppt.time = 0;#if Logprintf("[info]mppt.c:进入调整模式\r\n");#endif}return pwm;}
}
-END-
电赛专栏
关于2021年电赛的一些想法,看到就是赚到!
「2020年电赛」电源题详细技术方案,立即收藏!
2020年电赛题目,命题专家权威解析!
如何准备电赛?19年电赛经验总结!
电赛 | 19年全国一等奖,北航学子回忆录(上)
电赛 | 19年全国一等奖,北航学子回忆录(下)
「电赛分享」电源题,省一等奖!
2019年电赛综合测评怎么搞?国一师兄带你终极大测评!
-END-
最后,整理了一份电赛资源,近五年电赛真题的资源(代码、报告等),不过是付费的,如果有需要可以联系下方微信:
电赛 | 电源题软件如何准备?相关推荐
- 电赛猜题?我觉得没用,还不如做好这些!
01 前言 大家好,我是张巧龙,转眼又到22年电赛,这个公众号上有很多同学可能都参加过电赛,有毕业的已经工作的,也有没毕业的今年要参加. 我第一次接触电赛是在大一暑期,从参加电赛到指导学生参加电赛,转 ...
- 「第四篇」电赛控制题可以准备一些什么?
点击上方"大鱼机器人",选择"置顶/星标公众号" 福利干货,第一时间送达! 0 前言 在我看来,其实控制题是较好做(混)的一种题型,你懂我意思吧.控制题简单概 ...
- 2020电赛F题回顾——简易无接触温度测量与身份识别装置
2020电赛F题回顾--简易无接触温度测量与身份识别装置 第一次参加电赛,已经大三了,这也有可能是我的最后一次,不禁感慨时间过得真快.在实验室一起奋斗的夜晚既辛苦又幸福,感谢陪伴在我身边一起做电赛的同 ...
- 2022年电赛D题混沌信号发生器
2022年电赛D题混沌信号发生器分析 目录 前言 一.题目分析 二.设计过程 1.蔡氏电路 2.回转器 3.换档电路及跟随放大 总结 前言 这篇博客本来在比赛完的时候差不多写完了,但是因为一些个人原因 ...
- 2019年电赛D题《简易电路特性测试仪》全过程
本人为团队中负责硬件部分,为了准备2022年电赛,本队伍已经制作2019年和2021年电赛信号题,本次主要讲解为2019年电赛D题硬件部分,少部分为软件需要做的部分.后续会对整个硬件进行优化和整理. ...
- 【立创EDA开源推荐】005期 | 2019年电赛H题 电磁炮(激光版)
工程名称: 2019年电赛H题 电磁炮(激光版) 工程作者:zzxw 工程主页链接: https://oshwhub.com/kakaka/tu-ya-zhi-neng-yun-duo 开源协议: G ...
- 5_竞赛无人机搭积木式编程——以2021年电赛G题植保无人机国奖标准完整复现为例学习
竞赛无人机搭积木式编程 --以2021年电赛G题植保无人机国奖标准完整复现为例学习 首先我们需要了解下自动飞行任务执行过程几组关键变量的用法与实际作用效果: flight_subtask_cnt用于控 ...
- 2022电赛C题:小车跟踪(方案1+核心代码)
目录 前言 一.题目 二.方案1 1.材料清单 2.说明 三.核心代码 四.工程获取 前言 针对2022年电赛C题小车跟踪,本团队一共是做了两种方案: 第一种主要以摄像头(openmv)为 ...
- 2021年电赛 E题 数字传输
数字-模拟信号混合传输收发机(E题) 目录 题目 方案 工程文件 题目 (2) 实现数字信号传输. 首先键入4个0~9的一组数字,在发送端进行存储并显示,然后按下发送键对数字信号连续循环传输.在接收端 ...
最新文章
- 数字拆分问题算法回溯_回溯算法:求子集问题!
- Mybatis入门之动态sql
- WEB前端 vue学习一使用 vue-cli 搭建项目
- 数据存储之偏好设置NSUserDefaults
- hive表列字段显示
- 取消浏览器的默认样式
- libreoffice word转pdf时中文乱码问题解决
- Visio从安装到使用完整版
- 腾讯云上攻防战事(一)| 云上听风,不战而屈人之兵
- PaaS平台设计思想
- keil4 #pragma anon_unions
- Neural Summarization by Extracting Sentences and Words
- CSS特效三:简单的便签效果
- 微信小程序 day4
- windows双系统--WSL 安装使用
- windows系统的定时任务
- OPENSTREETMAP电力数据的情况
- x265-1.8版本-common/pixel.cpp注释
- require()------node js
- 《少年编程反汇编逆向调试入门》录制成功
热门文章
- Spring里Bean类的运行时小写之谜
- 如何免费试用SAP的Fiori应用
- 如何在SAP UI5应用里添加使用摄像头拍照的功能
- how is RFC to backend determined - maintenance view IWFNDV_MGDEAM
- support mobile touch event
- R3 data related to category and hierarchy mapping logic in CRM
- CRM Fiori my note应用的后台ABAP实现
- 借助Fiddle使用不同版本的UI5库文件进行测试
- 使用代码生成具有层级结构的IBASE
- Jerry Wang 2014年在SAP社区CRM板块的积分曾经一直占据第一