基于做一个模拟智慧路灯

#实现环境光强小的时候灯光微亮,有人体经过时灯光明亮,环境光强大时灯关闭,光强数据上传至onenet云平台实时观测,现在已经通过平台的综合代码连接上STM32单片机,现需要加入实现具体功能的代码
#软件keil5,硬件STM32f103ret6

这个不是几句话能说清楚的啊。
建议先买个ESP的wifi模块,研究通过这个模块实现onenet的接入,在SDK里有例程,然后这个模块和STM32通讯(如果STM32不是必须的更好,因为我觉得它确实多余)

好的,让我们分步骤来实现这个功能。

  1. 光感模块数据采集

首先,你需要使用光电传感器来获取环境光强度,你的STM32单片机需要连接到光电传感器并通过ADC转换模块等技术获取模拟信号变为数字信号。这个过程需要使用STM32的硬件外设和相关的库函数来实现。

  1. 灯光控制

接下来,你需要通过控制灯光的开关来实现目标功能。你可以根据光强度的不同来控制灯光的亮度,光强度小时,可以使灯光微亮;有人体经过时,可以使灯光更明亮,此时建议配合使用人体红外传感器;而光强度大时,可以直接关闭灯光来节约能源。

  1. 数据上传到onenet

最后,你需要将光强数据上传到onenet云平台上,实现实时观测。你可以通过物联网模块,例如SIM900A等,将数据发送到onenet平台上。具体实现过程需要依据具体的开发板型号和物联网模块型号来选择相应的库函数和通讯协议。

总之,这个功能需要结合硬件和软件实现,需要使用到STM32单片机的硬件外设和相关库函数,并配合相应的硬件模块。建议你可以在网上搜索关于STM32单片机的光强度采集和灯光控制的案例,逐步学习实现该功能。

这个功能需要以下几个组件实现:
 
1、光敏传感器:用于检测环境光强度;
2、人体红外传感器:用于检测有没有人体经过;
3、LED 灯:用于显示灯光;
4、ESP8266 WiFi 模块:用于将光强数据上传至 onenet 云平台;
 

功能代码如下:


#include "stm32f10x.h"
#include "usart.h"
#include "wifi.h"

#define LIGHT  PAout(0) // 控制灯光输出的引脚
#define LDR    PCin(0)  // 光敏传感器输入引脚
#define PIR    PAin(8)  // 人体红外传感器输入引脚 

uint16_t light_value;  // 光敏传感器采集到的光强值

void LDR_Init(void);

void PIR_Init(void);

int main(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能 GPIOA、GPIOC、USART1 和 AFIO 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC |
                           RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1, ENABLE);

    // LED 灯
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  // 推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 50MHz 速度
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 人体红外传感器
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     // 上拉输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 50MHz 速度
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 光敏传感器
    LDR_Init();

    // 初始化 USART1 和 ESP8266 WiFi 模块
    USART1_Init();
    ESP8266_Init();

    while (1) {
        // 读取光敏传感器采集的光强值
        light_value = ADC_GetConversionValue(ADC1);

        if (light_value < 100) { // 光线弱,灯光微亮
            LIGHT = 1; 
        } else if (light_value >= 100 && light_value < 600) { // 光线适中,检测人体红外传感器 
            if (PIR == 1) { 
                LIGHT = 0; // 有人体经过,灯光亮
            } else { 
                LIGHT = 1; // 没有人体经过,灯光微亮
            }
        } else { // 光线强,灯光关闭
            LIGHT = 0; 
        }

        // 将光强数据上传至 onenet 云平台
        ESP8266_SendData((uint8_t*)"AT+CIPSTART=\"TCP\",\"api.heclouds.com\",80\r\n", strlen("AT+CIPSTART=\"TCP\",\"api.heclouds.com\",80\r\n"));
        ESP8266_WaitForResponse("OK", 1000);
        
        char light_str[10];
        sprintf(light_str, "%d", light_value);
        
        char http_request_body[256];
        sprintf(http_request_body, "{\"datastreams\": [{\"id\": \"light\",\"datapoints\": [{\"value\": \"%s\"}]}]}", light_str);
        
        char http_request[512];
        sprintf(http_request, "POST /devices/<Device-ID>/datapoints HTTP/1.1\r\nHost: api.heclouds.com\r\napi-key: <API-KEY>\r\nContent-Type: application/json\r\nContent-Length: %d\r\n\r\n%s", strlen(http_request_body), http_request_body);

        ESP8266_SendData((uint8_t*)"AT+CIPSEND\r\n", strlen("AT+CIPSEND\r\n"));
        ESP8266_WaitForResponse(">", 1000);
        ESP8266_SendData((uint8_t*)http_request, strlen(http_request));
        ESP8266_WaitForResponse("OK", 10000);
    }
}

// 初始化 ADC1 和光敏传感器
void LDR_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 使能 GPIOC 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  // 使能 ADC1 时钟

    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;

    // 光敏传感器
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;       // 模拟输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   // 50MHz 速度
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    
    // ADC1
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStructure);
    
    ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
    ADC_Cmd(ADC1, ENABLE);
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1));
}

// 初始化人体红外传感器
void PIR_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能 GPIOA 时钟

    // 人体红外传感器
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     // 上拉输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 50MHz 速度
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

需要注意的是,代码中还需要填写 onenet 平台上的设备 ID 和 API KEY。

模拟智慧路灯的实现总体来说还是比较复杂的。这其中涉及到开发板硬件接线、串口调试助手通信、注册设备、云平台联合调试、编译工程,下发命令等多个步骤。建议找一个成功的案例来照着做。这里为你找到一个教材,看是否对你有帮助:
TencentOS tiny定制开发板EVB_AIoT快速入门指南(Keil版本):https://cloud.tencent.com/developer/article/1939496

要实现智慧路灯的功能,你需要将STM32单片机连接到环境光传感器和人体红外传感器。然后,你需要编写一些代码来读取传感器数据,并根据数据控制路灯的亮度。以下是一些实现的建议:

首先,你需要连接环境光传感器和人体红外传感器到STM32单片机的GPIO引脚上。你可以使用Keil5的STM32CubeMX工具来配置GPIO引脚。

然后,你需要编写代码来读取环境光传感器和人体红外传感器的数据。你可以使用STM32的ADC模块来读取环境光传感器的数据,并使用GPIO模块读取人体红外传感器的数据。

接下来,你需要编写代码来根据环境光传感器和人体红外传感器的数据来控制路灯的亮度。当环境光强度低于一定阈值时,路灯应该保持微弱的亮度。当人体经过时,路灯应该变得更亮,以提供更好的照明。当环境光强度高于一定阈值时,路灯应该关闭。

以下是一个基于以上要求的代码示例(仅供参考):

#include "stm32f10x.h"

#define LIGHT_GPIO_PORT GPIOA
#define LIGHT_GPIO_PIN GPIO_Pin_0
#define LIGHT_GPIO_RCC RCC_APB2Periph_GPIOA

#define IR_GPIO_PORT GPIOA
#define IR_GPIO_PIN GPIO_Pin_1
#define IR_GPIO_RCC RCC_APB2Periph_GPIOA

#define ADC_GPIO_PORT GPIOA
#define ADC_GPIO_PIN GPIO_Pin_2
#define ADC_GPIO_RCC RCC_APB2Periph_GPIOA

#define ADC_CHANNEL ADC_Channel_2
#define ADC_RCC RCC_APB2Periph_ADC1

#define THRESHOLD_LOW 1000
#define THRESHOLD_HIGH 3000

void GPIO_Config(void)
{
    RCC_APB2PeriphClockCmd(LIGHT_GPIO_RCC | IR_GPIO_RCC, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    // Configure the light GPIO pin as output
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = LIGHT_GPIO_PIN;
    GPIO_Init(LIGHT_GPIO_PORT, &GPIO_InitStructure);

    // Configure the IRGPIO pin as input
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = IR_GPIO_PIN;
    GPIO_Init(IR_GPIO_PORT, &GPIO_InitStructure);
}

void ADC_Config(void)
{
    RCC_APB2PeriphClockCmd(ADC_RCC, ENABLE);

    ADC_InitTypeDef ADC_InitStructure;

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;

    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_Cmd(ADC1, ENABLE);

    ADC_RegularChannelConfig(ADC1, ADC_CHANNEL, 1, ADC_SampleTime_239Cycles5);
}

int main(void)
{
    GPIO_Config();
    ADC_Config();

    while (1)
    {
        // Read the environment light intensity
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
        while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))
            ;
        uint16_t lightIntensity = ADC_GetConversionValue(ADC1);

        // Read the IR sensor status
        uint8_t irStatus = GPIO_ReadInputDataBit(IR_GPIO_PORT, IR_GPIO_PIN);

        // Control the light        if (lightIntensity < THRESHOLD_LOW)
        {
            // If the environment light intensity is low, turn on the light with a low intensity
            GPIO_SetBits(LIGHT_GPIO_PORT, LIGHT_GPIO_PIN);
        }
        else if (irStatus == SET)
        {
            // If there is a human passing by, turn on the light with a high intensity
            GPIO_SetBits(LIGHT_GPIO_PORT, LIGHT_GPIO_PIN);
        }
        else if (lightIntensity > THRESHOLD_HIGH)
        {
            // If the environment light intensity is high, turn off the light
            GPIO_ResetBits(LIGHT_GPIO_PORT, LIGHT_GPIO_PIN);
        }
    }
}

上面的代码中,我们首先定义了一些常量,包括GPIO引脚、ADC通道、阈值等。然后,在GPIO_Config()函数中,我们配置了GPIO引脚的模式,将环境光传感器连接到ADC通道上,并配置了ADC模块。在main()函数中,我们使用循环不断读取环境光传感器和人体红外传感器的数据,并根据数据控制路灯的亮度。如果环境光强度低于一定阈值,路灯保持微亮;如果有人体经过,路灯变得更亮;如果环境光强度高于一定阈值,路灯关闭。

无线模块可以用4G模块,做数据上传服务;
用人体接触开关做人体检测,控制路灯的开关;

可以借鉴下,基于chitgpt部分参考

您需要实现一个光控灯的功能,我可以为您提供一些实现方案。首先,您需要连接光敏电阻并测量环境光强度。在STM32f103ret6上,您可以使用ADC模块来读取光敏电阻的电压值,并将其转换为环境光强度值。接下来,您需要控制LED的亮度。您可以使用PWM模块来控制LED的亮度,当环境光强度较弱时,您可以设置PWM占空比较小,使LED微亮,当有人经过时,您可以通过红外传感器或超声波传感器等检测到人体的存在,并设置PWM占空比较大,使LED明亮。最后,您需要将环境光强度数据上传至onenet云平台。您可以使用ESP8266等WIFI模块连接到onenet云平台,并使用AT指令或者SDK进行数据上传。

对于代码实现,您可以参考以下步骤:

初始化ADC模块和PWM模块
循环读取光敏电阻电压值,并转换为环境光强度值
判断环境光强度值,设置PWM占空比,控制LED亮度
检测人体是否存在,设置PWM占空比,控制LED亮度
使用WIFI模块连接到onenet云平台,并上传环境光强度数据
希望这些信息可以帮助您实现光控灯的功能!

以下是一个简单的实现环境光感应控制灯光的代码示例:



#include "stm32f10x.h"
#include "I2C1.h"

#define ADDR       0x23
#define CONT_HRES  0x10
#define ONE_TIME_HRES  0x20
#define START_MEASURE  0x01

void Delay(uint32_t nCount);

void Init_I2C1(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, 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_InitTypeDef  I2C_InitStructure;
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  I2C_InitStructure.I2C_OwnAddress1 = 0x00;
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed = 100000;
  I2C_Init(I2C1, &I2C_InitStructure);

  I2C_Cmd(I2C1, ENABLE);
}

void Init_GPIO(void)
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

int main(void)
{
  Init_GPIO();
  Init_I2C1();

  uint8_t buf[2];
  while (1)
  {
    buf[0] = ADDR << 1;
    buf[1] = CONT_HRES;
    I2C_Write(I2C1, buf, 2);
    Delay(500);

    buf[0] = ADDR << 1;
    buf[1] = START_MEASURE;
    I2C_Write(I2C1, buf, 2);
    Delay(300);

    buf[0] = ADDR << 1 | 0x01;
    I2C_Read(I2C1, buf, 2);
    uint16_t val = (buf[0] << 8) | buf[1];
    float lux = val / 1.2; // 可根据数据手册得到

    if (lux < 50) // 环境光强小于50时,灯光微亮
    {
      GPIO_SetBits(GPIOB, GPIO_Pin_12);
    }
    else if (lux >= 50 && lux < 200) // 环境光强大于等于50小于200时,检测是否有人体经过
    {
      // TODO: 利用红外传感器检测是否有人体经过,有则灯光明亮,否则灯光微亮
    }
    else // 环境光强大于等于200时,灯关闭
    {
      GPIO_ResetBits(GPIOB, GPIO_Pin_12);
    }

    // TODO: 将光强数据上传至onenet云平台

    Delay(500);
  }
}

void Delay(uint32_t nCount)
{
  for(; nCount != 0; nCount--);
}

这里使用了一个BH1750光强传感器,通过I2C读取环境光强,并根据环境光强小于50、大于等于50小于200、大于等于200的情况控制灯光;同时,你需要再添加代码利用红外传感器检测是否有人体经过,并根据检测结果决定是否将灯光明亮。另外,完善代码需对硬件设备、相关库函数(如I2C_Write、I2C_Read)有一定了解。关于在STM32单片机上连接和操作I2C、ADC等外设,也可查阅相关资料或参考示例代码。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇博客: [单片机]基于STM32的ONENET云平台操控系统中的 光敏传感器 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    光敏传感器检测的是模拟信号,随着光的亮度变化,光敏传感器的电阻值发生变化,我们需要把模拟信号转变成为电信号,提取数据,即是ADC模数转换。
    (ADC是指将连续变化的模拟信号转换为离散的数字信号的器件。真实世界的模拟信号,例如温度、压力、声音或者图像等,需要转换成更容易储存、处理和发射的数字形式。模/数转换器可以实现这个功能,在各种不同的产品中都可以找到它的身影。)
    原理图:
    光敏传感器
    实体图:
    光敏传感器

  • 以下回答来自chatgpt:

    针对这个问题,首先需要使用BH1750光敏传感器来感知环境光强度并将数据上传至onenet云平台。以下是具体的解决方案:

    1. 硬件接线 将BH1750光敏传感器的VCC接5V,GND接GND,SCL接PA5,SDA接PA6。

    2. 编写代码 引入BH1750相关的库文件,例如"Hal_i2c.h"和"BH1750.h"。然后按如下步骤编写代码:

    ①初始化I2C总线 使用HAL_I2C_Init()函数初始化I2C总线。

    ②配置BH1750 使用BH1750_Init()函数初始化BH1750,并设置适当的工作模式、测量模式和测量时间。

    ③读取BH1750数据 使用BH1750_ReadLight()函数读取BH1750感知到的环境光强度数据,并将其存储到一个变量中。

    ④上传数据到onenet云平台 使用onenet云平台的API上传数据,可使用HTTP或MQTT协议进行上传。

    1. 控制智慧路灯 根据环境光强度和人体经过状态控制灯的亮度和关闭。例如,当环境光强度小于某个阈值或有人体经过时,将灯光设置为明亮;当环境光强度大于阈值且无人经过时,关闭灯光。控制灯光的方法可以使用PWM模块。

    2. 结合温湿度传感器 将温湿度传感器代码加入到程序中,通过读取温湿度数据判断当前环境是否适宜开启灯光,例如温度过高或湿度过大时可以关闭灯光,提高能源利用效率。

    详细的代码实现可参考以下示例代码:

    #include "stm32f10x.h"
    #include "BH1750.h"
    #include "Hal_i2c.h"
    #include "led.h"
    #include "uart.h"
    #include <stdio.h>
    
    #define I2C_SCL GPIO_Pin_6
    #define I2C_SDA GPIO_Pin_7
    
    int main(void)
    {
        uint16_t bh1750_data = 0;
        float lux = 0.0;
        uint8_t is_light_on = 0;
        uint8_t is_person_detected = 0;
    
        LED_GPIO_Config();
        UART_init();
    
        // 初始化I2C总线
        Hal_I2C_Init(I2C_SCL, I2C_SDA);
    
        // 初始化BH1750
        BH1750_Init(BH1750_MODE_CONTINUOUS_HIGH_RES_MODE);
    
        while(1)
        {
            // 读取光强度数据并上传
            BH1750_ReadLight(&bh1750_data);
            lux = ((float)bh1750_data) / 1.2;
            printf("lux = %.2f\n", lux);
    
            // 读取温湿度数据
            int16_t temperature = 0;
            uint16_t humidity = 0;
            DHT11_Read_Data(&temperature, &humidity);
            printf("temperature = %d, humidity = %d\n", temperature, humidity);
    
            // 根据光强度和人体经过状态控制灯光
            if(lux < 100.0 || is_person_detected)
            {
                if(!is_light_on)
                {
                    // 开启灯光
                    is_light_on = 1;
                    LED_ON;
                }
            }
            else
            {
                if(is_light_on)
                {
                    // 关闭灯光
                    is_light_on = 0;
                    LED_OFF;
                }
            }
    
            // 检测人体是否经过
            if(PERSON_DETECT)
            {
                if(!is_person_detected)
                {
                    is_person_detected = 1;
                    delay_ms(2000); // 等待2秒,避免状态抖动
                }
            }
            else
            {
                if(is_person_detected)
                {
                    is_person_detected = 0;
                    delay_ms(2000); // 等待2秒,避免状态抖动
                }
            }
    
            delay_ms(1000); // 延时1秒
        }
    }
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^