项目介绍
喜欢看书,但是又担心环境照度是否足够,所以就做了一个便携照度测量仪。
照度计又称照度仪(或称勒克斯计),是一种专门测量光度、亮度的仪器仪表,由主机和一个光传感器组成,常用于测量室内灯具的照度。它所测的光照强度就是物体被照明的程度,也即物体表面所得到的光通量与被照面积之比。照度计通常是由硒光电池或硅光电池,以及微安表组成。照度测量应采用不低于一级的照度计。照度计由光度头(又称受光探头,包括接收器、V(λ)对滤光器、余弦修正器)和读数显示器两部分组成。
市场应用介绍
家庭使用,可携带式体积小、重量轻。
项目设计思路
本次设计将采用STM32G0作为主控芯片,BH1750FVI进行亮度采集。
项目方案框图和原理图
设计中用到规定厂商的元器件介绍
1.STM32G031
STM32G031x4/x6/x8主流微控制器基于高性能Arm Cortex-M0+ 32位RISC内核,工作频率高达64 MHz。它们具有高集成度,适用于消费、工业和家电领域的广泛应用,并为物联网 (IoT) 解决方案做好准备。
这些器件集成了存储器保护单元 (MPU)、高速嵌入式存储器(8 KB SRAM 和高达 64 KB 的闪存程序存储器,具有读保护、写保护、专有代码保护和安全区域)、DMA、广泛的系统功能、增强型 I/O 和外设。这些器件提供标准通信接口(两个I2Cs,两个 SPI / 一个 I2S和两个USART)、一个12-bit ADC (2.5 MSps)、一个内部基准电压缓冲器、一个低功耗RTC、一个以高达两倍CPU频率运行的高级控制PWM定时器、四个通用16位定时器、一个32位通用定时器、两个低功耗16位定时器、两个看门狗定时器和一个SysTick定时器。
这些器件可在 -40 至 125°C 的环境温度和 1.7 V 至 3.6 V 的电源电压下工作。 优化的动态功耗与一套全面的节能模式、低功耗定时器和低功耗UART相结合,允许设计低功耗应用。
VBAT直接电池输入允许保持RTC和备份寄存器供电。
这些器件采用 8 至 48 引脚封装。
2.BH1750FVI
BH1750FVI数字光照传感器是测量环境的光照强度的数字传感器,它能够通过I2C接口与MCU连接,输出数字信号。该传感器采用亮度校准和温度校准的先进技术,能够在各种光线条件下提供准确的光照测量结果。其超小的封装和低功耗特性,使得它成为了广泛应用于各种便携式智能设备、LED照明以及室内智能家居与办公环境的理想选择。
BH1750FVI传感器特性如下:
1.补偿功能:传感器采用了先进亮度校准和温度校准技术,能够提供高精度的光照测量结果。
2.数字接口:传感器具有I2C数字接口,可与微控制器(MCU)直接连接。
3.全面量程:传感器测量范围为0到65535(等于0.11到100000lx)。
4.低功耗特性:传感器在低功耗模式下只需消耗1uA的电流。
5.小型封装:BH1750FVI使用极小的封装,可在小型的智能设备中使用。
3.XC6206
XC6206 系列是一款高精度低功耗的 LDO 线性稳压芯片,即使在输出电流较大的情况下,其输入与输出之间的压差依然较小。其常见的 SOT-23-3 封装通常拥有 输入、输出、接地 三个引脚,内部包含了限流电路、驱动三极管、高精度参考电压源、误差校正电路:XC6206 系列的性能参数如下:
- 最大输出电流 200mA (3.0V type)
- 输入输出压差 250mV @ 100mA (3.0V type)
- 最大工作电压 6.0V
- 输出电压范围 1.2V ~ 5.0V (0.1V 递进)
- 输出精度 $$、$\pm30mV@V_{OUT}<1.5V$、$\pm1\% @V_{OUT}\ge2.0V$
- 低功耗 典型值为 1.0 μA
- 输出电容类型 可以兼容低 ESR 的陶瓷电容
- 保护措施 内置限流电路
- 工作环境温度 -40℃ ~ 85℃
XC6206 系列可以选用较低等效串联电阻(ESR,Equivalent Series Resistance)的陶瓷电容,并且可以由内部的限流电路提供输出引脚的短路保护。
PCB绘制打板介绍及遇到的问题和解决方法
绘制的时候,主芯片不小心镜像了,焊接的时候,芯片只能反过来焊接。
关键代码及说明
主要代码
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_I2C2_Init();
MX_TIM1_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
OLED_Init();
BH1750_Init();
while(1)
{
HAL_Delay(200);
OLED_ShowNum(0,0,BH1750_Read(),5,32);
OLED_ShowString(80,0,"Lux",32);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
}
OLED驱动
#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"
#include "i2c.h"
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
uint8_t data[1] = {IIC_Command};
HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT, data, 1, 0xff);
}
/**********************************************
IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
uint8_t data[1] = {IIC_Data};
HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT, data, 1, 0xff);
}
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
if(cmd)
{
Write_IIC_Data(dat);
}
else
{
Write_IIC_Command(dat);
}
}
/********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{
unsigned char m,n;
for(m=0;m<8;m++)
{
OLED_WR_Byte(0xb0+m,0); //page0-page1
OLED_WR_Byte(0x00,0); //low column start address
OLED_WR_Byte(0x10,0); //high column start address
for(n=0;n<128;n++)
{
OLED_WR_Byte(fill_Data,1);
}
}
}
//坐标设置
void OLED_Set_Pos(unsigned char x, unsigned char y)
{ OLED_WR_Byte(0xb0+y,OLED_CMD);
OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
OLED_WR_Byte((x&0x0f),OLED_CMD);
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
} //更新显示
}
void OLED_On(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA);
} //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 16/12
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
{
unsigned char c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>Max_Column-1)
{
x=0;
y=y+2;
}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
}
else if(Char_Size ==32)
{
OLED_Set_Pos(x,y);
for(i=0;i<16;i++)
OLED_WR_Byte(F16X32[c*64+i],OLED_DATA);
OLED_Set_Pos(x,y+1);
for(i=0;i<16;i++)
OLED_WR_Byte(F16X32[c*64+i+16],OLED_DATA);
OLED_Set_Pos(x,y+2);
for(i=0;i<16;i++)
OLED_WR_Byte(F16X32[c*64+i+16*2],OLED_DATA);
OLED_Set_Pos(x,y+3);
for(i=0;i<16;i++)
OLED_WR_Byte(F16X32[c*64+i+16*3],OLED_DATA);
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
}
//m^n函数
uint32_t oled_pow(uint8_t m,uint8_t n)
{
uint32_t result=1;
while(n--)result*=m;
return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式 0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size2)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
}
}
//显示一个字符号串
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size)
{
unsigned char j=0;
while (chr[j]!='\0')
{
if(Char_Size == 16)
{
OLED_ShowChar(x,y,chr[j],Char_Size);
x+=8;
if(x>120)
{
x=0;
y+=2;
}
j++;
}
else if(Char_Size == 32)
{
OLED_ShowChar(x,y,chr[j],Char_Size);
x+=16;
j++;
}
}
}
//显示汉字
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
{
uint8_t t,adder=0;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
adder+=1;
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
adder+=1;
}
}
//初始化SSD1306
void OLED_Init(void)
{
HAL_Delay(200);
OLED_WR_Byte(0xAE,OLED_CMD);//关闭显示
OLED_WR_Byte(0x40,OLED_CMD);//---set low column address
OLED_WR_Byte(0xB0,OLED_CMD);//---set high column address
OLED_WR_Byte(0xC8,OLED_CMD);//-not offset
OLED_WR_Byte(0x81,OLED_CMD);//设置对比度
OLED_WR_Byte(0xff,OLED_CMD);
OLED_WR_Byte(0xa1,OLED_CMD);//段重定向设置
OLED_WR_Byte(0xa6,OLED_CMD);//
OLED_WR_Byte(0xa8,OLED_CMD);//设置驱动路数
OLED_WR_Byte(0x1f,OLED_CMD);
OLED_WR_Byte(0xd3,OLED_CMD);
OLED_WR_Byte(0x00,OLED_CMD);
OLED_WR_Byte(0xd5,OLED_CMD);
OLED_WR_Byte(0xf0,OLED_CMD);
OLED_WR_Byte(0xd9,OLED_CMD);
OLED_WR_Byte(0x22,OLED_CMD);
OLED_WR_Byte(0xda,OLED_CMD);
OLED_WR_Byte(0x02,OLED_CMD);
OLED_WR_Byte(0xdb,OLED_CMD);
OLED_WR_Byte(0x49,OLED_CMD);
OLED_WR_Byte(0x8d,OLED_CMD);
OLED_WR_Byte(0x14,OLED_CMD);
OLED_WR_Byte(0xaf,OLED_CMD);
OLED_Clear();
}
BH1750驱动
#include "BH1750.h"
#include "i2c.h"
uint16_t BH1750_Read(void)
{
uint8_t data[2];
HAL_I2C_Master_Receive(&hi2c2, 0x46, data, 2, 0xff);
return (uint16_t)((float)(((uint16_t)data[0]<<8) | data[1])/1.2);
}
//初始化BH1750,根据需要请参考pdf进行修改****
void BH1750_Init()
{
uint8_t data[1] = {0x01};
HAL_I2C_Master_Transmit(&hi2c2, 0x46, data, 1, 0xff);
data[0] = 0x10;
HAL_I2C_Master_Transmit(&hi2c2, 0x46, data, 1, 0xff);
}
功能展示及说明
设备裸机样式
卧室灯下测量效果
手机闪光灯照射效果
对本大赛的心得体会
无,活动挺好