白柴的推荐语:
星座图标,出乎意料的图案,意外的好看\(^o^)/
1.前期准备阶段
5.1号就开始准备材料了,用了eepw提供的墙纸。还有自己买的灯罩,32位单片机,杜邦线,蓝牙模块等等。所以,接下来就是等待材料到来时候了!刚开始有些意外,定制的亚克力板子由于没有和老板商量好,导致板子制作出来只有一小部分,所幸板子买的早。于是在5.8时候所有材料就送到我的手中。
所有材料到了就开始我的制作了!
2.制作我的星空灯
首先我使用的是STM32单片机,使用该单片机的原因是因为速度快,更重要的原因是除了这个其他的我不会。从网上仔细的学习了WS2812灯带的使用方法之后。发现他有以下的特性:
1)上电时,WS2812数据IO为低电平保持。
2)空闲时,IO为低电平。
3)数据发送完毕后,保持电平,超过规格书上定义的RESET时间(只有低电平时间超过280us,就可以认为是RESET.)
从而可见它比其他灯带操作还是更难的。接着对代码进行编写和优化。
灯带部分代码:
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { HAL_TIM_PWM_Stop_DMA(&htim1,TIM_CHANNEL_1); } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(Buffer>='A' && Buffer <='I') { Mode_Led = Buffer; printf("µÆ¹âģʽ£º%c",Mode_Led); } if(Buffer == 'J') { Mode_wait +=10; if(Mode_wait==250) Mode_wait=240; printf("µÆ¹âËٶȣº%d",300-Mode_wait); } if(Buffer == 'K') { Mode_wait -=10; if(Mode_wait==60) Mode_wait=70; printf("µÆ¹âËٶȣº%d",300-Mode_wait); } HAL_UART_Receive_IT(&huart2,&Buffer, 1); } void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin) { switch(GPIO_Pin) { case GPIO_PIN_13:Mode_Led++; if(Mode_Led == 'J') Mode_Led ='A';break; } } void WS281x_SetPixelColor(uint16_t n, uint32_t GRBColor) { uint8_t i; if (n < LED_NUMS) { for (i = 0; i < 24; ++i) RGB_buffur[24 * n + i] = ((GRBColor << i) & 0X800000) ? ONE_PULSE : ZERO_PULSE; } } uint32_t WS281x_Color(uint8_t red, uint8_t green, uint8_t blue) { return green << 16 | red << 8 | blue; } uint32_t Wheel(uint8_t WheelPos) { WheelPos = 255 - WheelPos; if (WheelPos < 85) { return WS281x_Color(255 - WheelPos * 3, 0, WheelPos * 3); } if (WheelPos < 170) { WheelPos -= 85; return WS281x_Color(0, WheelPos * 3, 255 - WheelPos * 3); } WheelPos -= 170; return WS281x_Color(WheelPos * 3, 255 - WheelPos * 3, 0); } void Mode2_LED(uint8_t wait) { uint32_t timestamp = HAL_GetTick(); uint16_t i; static uint8_t j; static uint32_t next_time = 0; uint32_t flag = 0; if (next_time < wait) { if ((uint64_t)timestamp + wait - next_time > 0) flag = 1; } else if (timestamp > next_time) { flag = 1; } if (flag) { j++; next_time = timestamp + wait; for (i = 0; i < LED_NUMS; i++) { WS281x_SetPixelColor(i, Wheel((i + j) & 255)); } } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN); } void Mode1_LED(uint8_t wait) { uint32_t timestamp = HAL_GetTick(); uint16_t i; static uint8_t j; static uint32_t next_time = 0; static uint8_t loop = 0; if (loop == 0) next_time = timestamp; loop = 1; //Ê״ε÷Óóõʼ»¯ if ((timestamp > next_time)) // && (timestamp - next_time < wait*5)) { j++; next_time = timestamp + wait; for (i = 0; i < LED_NUMS; i++) { WS281x_SetPixelColor(i, Wheel(((i * 256 / (LED_NUMS)) + j) & 255)); } } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN); } void Mode3_LED(void)//È«ºì { uint16_t i; for (i = 0; i < LED_NUMS; i++) { WS281x_SetPixelColor(i,0x0ff000); } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN); } void Mode4_LED(void)//È«À¶ { uint16_t i; for (i = 0; i < LED_NUMS; i++) { WS281x_SetPixelColor(i,0x000ff0); } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN); } void Mode5_LED(void)//È«ÂÌ { uint16_t i; for (i = 0; i < LED_NUMS; i++) { WS281x_SetPixelColor(i,0xf0000f); } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN); } void Mode6_LED(uint8_t wait)//È«ºìºôÎü { static uint32_t led_init=0x000000; uint16_t i;static uint8_t temp =0; uint32_t timestamp = HAL_GetTick(); static uint32_t next_time = 0; static uint8_t loop = 0; if (loop == 0) next_time = timestamp; loop = 1; //Ê״ε÷Óóõʼ»¯ if ((timestamp > next_time)) // && (timestamp - next_time < wait*5)) { next_time = timestamp + wait; if((led_init < 0x02F000) && (temp == 0)) { led_init +=0x001000; if(led_init == 0x02F000) temp=1; }else{ led_init -=0x001000; if(led_init == 0x000000) temp=0; } for (i = 0; i < LED_NUMS; i++) { WS281x_SetPixelColor(i,led_init); } } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN); } void Mode7_LED(uint8_t wait)//È«À¶ºôÎü { static uint32_t led_init=0x000000; uint16_t i;static uint8_t temp =0; uint32_t timestamp = HAL_GetTick(); static uint32_t next_time = 0; static uint8_t loop = 0; if (loop == 0) next_time = timestamp; loop = 1; //Ê״ε÷Óóõʼ»¯ if ((timestamp > next_time)) // && (timestamp - next_time < wait*5)) { next_time = timestamp + wait; for (i = 0; i < LED_NUMS; i++) { WS281x_SetPixelColor(i,led_init); } if((led_init <0x0002f0) && (temp == 0)) { led_init +=0x000010; if(led_init == 0x0002f0) temp=1; }else{ led_init -=0x000010; if(led_init == 0x000000) temp=0; } } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN); } void Mode8_LED(uint8_t wait)//È«Â̺ôÎü { static uint32_t led_init=0x000000; uint16_t i;static uint8_t temp =0; uint32_t timestamp = HAL_GetTick(); static uint32_t next_time = 0; static uint8_t loop = 0; if (loop == 0) next_time = timestamp; loop = 1; //Ê״ε÷Óóõʼ»¯ if ((timestamp > next_time)) // && (timestamp - next_time < wait*5)) { next_time = timestamp + wait; for (i = 0; i < LED_NUMS; i++) { WS281x_SetPixelColor(i,led_init); } if((led_init <0xf00000) && (temp == 0)) { led_init +=0x100000; if(led_init == 0xf00000) temp=1; }else{ led_init -=0x100000; if(led_init == 0x000000) temp=0; } } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN); } void Mode9_LED(uint8_t wait)//Ѭ»· { static uint8_t temp =0,loop_A = 0; uint32_t timestamp = HAL_GetTick(); static uint32_t next_time = 0; static uint8_t loop = 0; if (loop == 0) next_time = timestamp; loop = 1; //Ê״ε÷Óóõʼ»¯ if ((timestamp > next_time)) // && (timestamp - next_time < wait*5)) { next_time = timestamp + wait; if(loop_A == 0){ WS281x_SetPixelColor(temp,0xf0000f); loop_A = 1; } else{ WS281x_SetPixelColor(temp,0x000000); loop_A = 0; temp++; if(temp == LED_NUMS) temp=0; } } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN); }
这时候基本功能已经完成大半了,和手机如何进行连接。有两种方案:1·使用ESp8266利用WIFI连接。优点是速度快。缺点是我不会。2·使用HC-06模块用蓝牙连接,优点是简单,缺点是速度太慢了。但是这里用这个完全就够了。
主机:用于向从机下发指令,能够搜索从机并主动建立连接的一方。
从机:用于接收主机下发的命令,不能主动建立连接,只能等别人连接自己。(HC-06只能工作在从机模式下。)
主从一体:能够在主机和从机模式间切换,即可做主机也可作从机。如:HC-05既可以设置为主机也可以设置为从机。
代码如下:
static void MX_USART2_UART_Init(void) { /* USER CODE BEGIN USART2_Init 0 */ /* USER CODE END USART2_Init 0 */ /* USER CODE BEGIN USART2_Init 1 */ /* USER CODE END USART2_Init 1 */ huart2.Instance = USART2; huart2.Init.BaudRate = 9600; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1; huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) { Error_Handler(); } if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) { Error_Handler(); } if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART2_Init 2 */ /* USER CODE END USART2_Init 2 */ } /** * Enable DMA controller clock */ static void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Channel1_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); }
接下来就是重头戏,开始灯罩的设计。由于创造能力太差,我就雕刻的不咋好看,不过可以凑合着看:
3.完成
让我们一起看看效果原图吧!
在宿舍,效果不是不很好。但是,谁收到都会感动哭了!