树莓派mqtt协议连接阿里云物联网平台,手机端获取数据并控制

树莓派mqtt协议连接阿里云物联网平台(二)

树莓派配置

硬件连接 i2c1 连接 AM2320温湿度传感器。
i2c0 连接 GY30-BH1750光强传感器。
用到两个库
一个是paho.mqtt.embedded-c-master.zip github上维护的c语言版本的mqtt协议库。链接
另一个是 博通的io操作库 bcm2835-1.68.tar.gz 链接

我的工程里并没有编译成so,我直接把源码里用的c文件复制过来了。
在这里插入图片描述
在这里插入图片描述
还有bcm2835 库有个宏 定义了i2c1 ,默认i2c0 是不编译的,我用了i2c0,库函数让我改了。

AM2320 读取函数

int get_am2320_data(int *temperature,int *himudity)
{
    uint8_t w_temp_data[AM2320_CMD_LEMGTH] = {0}; 
    uint8_t r_temp_data[AM2320_TEMP_RETURN_LENGTH] = {0};   

    iot_info("run get data from am2320\n");

    if (!bcm2835_init())
    {
        iot_error("bcm2835_init failed. Are you running as root??\n");
        return FAILURE;
    }
   
    if (!bcm2835_i2c_begin(I2C_1))
    {
        iot_error("bcm2835_i2c_begin failed. Are you running as root??\n");
	    return FAILURE;
    }
    bcm2835_i2c_setSlaveAddress(I2C_1,AM2320_DEVICE_ADDR);
    bcm2835_i2c_set_baudrate(I2C_1,AM2320_BAUDRATE);

    bcm2835_i2c_write(I2C_1,NULL,0); //wark up
    usleep(30*1000);
    w_temp_data[0] = AM2320_FUNCTION_CODE;
	w_temp_data[1] = AM2320_TEMP_HUMIDITY_ADDR;
	w_temp_data[2] = AM2320_TEMP_HUMIDITY_LENGTH;

    bcm2835_i2c_write(I2C_1,w_temp_data,AM2320_CMD_LEMGTH);
    usleep(30*1000); 
    bcm2835_i2c_read(I2C_1,r_temp_data,AM2320_TEMP_RETURN_LENGTH);
 
    *himudity = (((r_temp_data[2] << 8) | (r_temp_data[3])) & 0xffff);
    *temperature = (((r_temp_data[4] << 8)| (r_temp_data[5])) & 0xffff);
    bcm2835_i2c_end(I2C_1);   
    bcm2835_close();
    return SUCCESS;
}

BH1750 读取函数

int get_light_value(uint16_t *light_value)
{
    uint8_t r_light_data[2] = {0};
    uint8_t high_mode = BH_HMODE_RESOLUTION;

    iot_info("get_light_value now\n");
    if (!bcm2835_init())
    {
        iot_error("bcm2835_init failed. Are you running as root??\n");
        return FAILURE;
    }
   
    if (!bcm2835_i2c_begin(I2C_0))
    {
        iot_error("bcm2835_i2c_begin failed. Are you running as root??\n");
	    return FAILURE;
    }

    bcm2835_i2c_setSlaveAddress(I2C_0,BH1750_DEVICE_ADDR);
    bcm2835_i2c_set_baudrate(I2C_0,BH1750_BAUDRATE);

    bcm2835_i2c_write(I2C_0,&high_mode,1);
    usleep(180 * 1000);
    bcm2835_i2c_read(I2C_0,r_light_data,2);
       
    bcm2835_i2c_end(I2C_0);   
    bcm2835_close();

    *light_value = ((r_light_data[0] << 8) | r_light_data[1]);
    return SUCCESS;
}

int init_bh1750()
{
    uint8_t power_on = BH_POWER_ON;
    uint8_t reset = BH_RESET;
    iot_info("init_bh1750 now\n");
    if (!bcm2835_init())
    {
        iot_error("bcm2835_init failed. Are you running as root??\n");
        return FAILURE;
    }
      iot_info("init_bh1750 now\n");
    if (!bcm2835_i2c_begin(I2C_0))
    {
        iot_error("bcm2835_i2c_begin failed. Are you running as root??\n");
	    return FAILURE;
    }
   
    bcm2835_i2c_setSlaveAddress(I2C_0,BH1750_DEVICE_ADDR);
    bcm2835_i2c_set_baudrate(I2C_0,BH1750_BAUDRATE);
    
    bcm2835_i2c_write(I2C_0,&power_on,1);
    usleep(10 * 1000);
    bcm2835_i2c_write(I2C_0,&reset,1);
       
    bcm2835_i2c_end(I2C_0);   
    bcm2835_close();
    return SUCCESS;
}

还有个问题,我在几个线程里操作 博通这个库,如果抢占资源,会出现段错误,所以要保证一个时间点只要一个线程去操作博通这个库。这里用到了线程锁。

void *get_sensor_data_function(void *arg)
{
    int temp;
    int himudity;
    uint16_t light_value;
    int ret = 0;

    pthread_mutex_lock(&m_mutex);
    init_bh1750();
    pthread_mutex_unlock(&m_mutex);
    while (1){
        
        cJSON * root =  cJSON_CreateObject();
        cJSON * item =  cJSON_CreateObject();
        pthread_mutex_lock(&m_mutex);
        get_am2320_data(&temp,&himudity);
        pthread_mutex_unlock(&m_mutex);
       
        pthread_mutex_lock(&m_mutex);
        get_light_value(&light_value);
        pthread_mutex_unlock(&m_mutex);

        //iot_info("get_am2320_data temp = %d himudity = %d\n",temp,himudity);
        //iot_info("get_bh1750_data light = %d\n",light_value);
        //iot_info("get ali connect status  = %s\n",Iot_mqtt.iotstatus == IOT_STATUS_CONNECT ? "Connect" : "Disconect");

        cJSON_AddItemToObject(root,"method",cJSON_CreateString("thing.event.property.post"));
        cJSON_AddItemToObject(root,"id",cJSON_CreateString("01406633"));
        cJSON_AddItemToObject(root,"params",item);
        cJSON_AddItemToObject(item,"RoomTemp",cJSON_CreateNumber((float)temp/10.0));
        cJSON_AddItemToObject(item,"RoomHumidity",cJSON_CreateNumber((float)himudity/10.0));
        cJSON_AddItemToObject(item,"RoomLight",cJSON_CreateNumber((light_value * 10)/12));
        cJSON_AddItemToObject(root,"version",cJSON_CreateString("1.0.0"));

        char *payload_data = cJSON_Print(root);
        //iot_info("payload data = %s\n",payload_data); 

        if (Iot_mqtt.iotstatus == IOT_STATUS_CONNECT){

            ret = mqtt_data_write(payload_data,strlen(payload_data),0);
        }   
        iot_info("payload sensor data  to ali yun %s.\n",ret == 0 ? "Success" : "fail"); 
        sleep(3);
    }

mqtt移植,打开我们下载的paho.mqtt.embedded-c-master文件,里面用到的文件就那几个,MQTTPacket/src ,
在这里插入图片描述
这两个文件
在这里插入图片描述
还有两个文件
在这里插入图片描述
工程里iot_mqtt.c是登录文件。

void iot_mqtt_init(Cloud_MQTT_t *piot_mqtt) 
{
    memset(piot_mqtt, '\0', sizeof(Cloud_MQTT_t));

    memcpy(piot_mqtt->sub_topic, MQTT_SUB_TOPIC,strlen(MQTT_SUB_TOPIC));	
    iot_info("subscribe:%s\n", piot_mqtt->sub_topic);

    memcpy(piot_mqtt->pub_topic, MQTT_PUSH_TOPIC,strlen(MQTT_PUSH_TOPIC));	
    iot_info("pub:%s\n", piot_mqtt->pub_topic);
    piot_mqtt->DataArrived_Cb = mqtt_data_rx_cb;
}

void MQTTMessageArrived_Cb(MessageData* md)
{
    MQTTMessage *message = md->message; 

    Cloud_MQTT_t *piot_mqtt = &Iot_mqtt;

    if (NULL != piot_mqtt->DataArrived_Cb) {
        piot_mqtt->DataArrived_Cb((void *)message->payload, message->payloadlen);//异步消息体
    }
}

int mqtt_device_connect(Cloud_MQTT_t *piot_mqtt)
{
    int ret = 0;
    NewNetwork(&piot_mqtt->Network);
    iot_info("topic = %s\n", piot_mqtt->sub_topic);
    ret = ConnectNetwork(&piot_mqtt->Network, MQTT_HOST, (int)MQTT_PORT);	
    if (ret != 0) {
        iot_error("mqtt connect network fail \n");
        ret = CONNECT_NET_ERROR;
        goto error;
    }
    MQTTClient(&piot_mqtt->Client, &piot_mqtt->Network, 1000, piot_mqtt->mqtt_buffer, MQTT_BUF_SIZE, piot_mqtt->mqtt_read_buffer, MQTT_BUF_SIZE);
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;

    if (piot_mqtt->willFlag) {
        data.willFlag = 1;
        memcpy(&data.will, &piot_mqtt->will, sizeof(MQTTPacket_willOptions));
    } else {
        data.willFlag = 0;
    }
    data.MQTTVersion = 3;
    data.clientID.cstring = MQTT_CLIENT_ID;
    data.username.cstring = MQTT_USER;
    data.password.cstring = MQTT_PASS;
    data.keepAliveInterval = 30;
    data.cleansession = 1;
    
    ret = MQTTConnect(&piot_mqtt->Client, &data);
    if (ret) {
        iot_error("mqtt connect broker fail \n");
        iot_error("rc = %d\n", ret);
        ret = MQTT_CONNECT_ERROR;
        goto error;
    }
    ret = MQTTSubscribe(&piot_mqtt->Client, piot_mqtt->sub_topic, opts.qos, MQTTMessageArrived_Cb);
    if (ret) {
        iot_error("mqtt subscribe fail \n");
        ret = MQTTSUBSCRIBE_ERROR;
        goto error;
    }
    Iot_mqtt.iotstatus = IOT_STATUS_CONNECT;
    iot_info("connect %s %s\n", MQTT_HOST,ret == 0 ? "Success" : "failure");
    return CONNECT_SUCCESS;
error:
    return ret;
}

在这里插入图片描述
登录用的host port 以及用户名 密码 clinet_ID 我直接代码里写死的,这里根据上篇讲到的那个product_key device_name 还有那个DeviceSecret来生成的,网上有个工具,复制进去生成如下:
在这里插入图片描述
连接到服务器,可以在后台看见设备上线了。
树莓派上传数据到云端用的函数为

int mqtt_data_write(char *pbuf, int len, char retain)
{
    Cloud_MQTT_t *piot_mqtt = &Iot_mqtt; 
    int ret = 0;
    MQTTMessage message;
    char my_topic[128] = {0};

    strcpy(my_topic, piot_mqtt->pub_topic);

    //iot_info("publish topic is :%s\r\n", my_topic);
    //iot_info("mqtt tx len = %d\r\n", len);
    message.payload = (void *)pbuf;
    message.payloadlen = len;
    message.dup = 0;
    message.qos = QOS0;
    if (retain) {
        message.retained = 1;
    } else {
        message.retained = 0;
    }

    ret = MQTTPublish(&piot_mqtt->Client, my_topic, &message);	//发布一个主题
    return ret;
}

这里的topic 就是我们前一篇讲的,/sys/a1HozAJNWVx/raspberrypi/thing/event/property/post
但是上传数据要用JSON格式,所以工程里添加了CJSON库。


        cJSON_AddItemToObject(root,"method",cJSON_CreateString("thing.event.property.post"));
        cJSON_AddItemToObject(root,"id",cJSON_CreateString("01406633"));
        cJSON_AddItemToObject(root,"params",item);
        cJSON_AddItemToObject(item,"RoomTemp",cJSON_CreateNumber((float)temp/10.0));
        cJSON_AddItemToObject(item,"RoomHumidity",cJSON_CreateNumber((float)himudity/10.0));
        cJSON_AddItemToObject(item,"RoomLight",cJSON_CreateNumber((light_value * 10)/12));
        cJSON_AddItemToObject(root,"version",cJSON_CreateString("1.0.0"));

        char *payload_data = cJSON_Print(root);
        iot_info("payload data = %s\n",payload_data); 

这里的id随便写,app打印出来的格式为
在这里插入图片描述
这样云端就会收到设备端的数据了。
在这里插入图片描述
在这里插入图片描述

工程是cmake 管理的。下载后cmake CMakeLists.txt ;make命令编译,
运行sudo ./iotApp 即可。

在这里插入图片描述

在这里插入图片描述
源码

<think>嗯,用户想了解如何实现车辆的远程控制技术方案和实现方式。首先,我需要明确远程控制车的基本组成部分。通常来说,远程控制需要几个关键部分:控制端、通信模块、车载控制单元和执行机构。 首先,控制端可以是手机APP或者电脑软件,用户在这里发送指令。然后,通信模块负责将指令传输到车辆上。常用的通信方式有4G/5G、Wi-Fi、蓝牙或者专用的无线电频段。比如,4G/5G适合远距离控制,而Wi-Fi和蓝牙可能更适合短距离。 接下来,车载控制单元需要接收指令解析,然后驱动执行机构。执行机构包括电机、舵机等,用来控制车辆的方向、速度等。同时,车辆还需要传感器来反馈实时数据,比如摄像头、GPS、陀螺仪等,这样控制端才能获得车辆的状态信息,实现闭环控制。 安全性也是不可忽视的。通信过程需要加密,防止被黑客攻击。此外,故障保护机制也很重要,比如信号丢失时车辆自动停车。 然后,我得考虑具体的实现步骤。比如,选择适合的通信协议,设计控制指令的格式,编写车载控制单元的代码,以及开发用户界面。可能还需要集成传感器数据,实现自动避障或者路径规划等高级功能。 用户可能还关心现有的技术方案,比如使用树莓派或Arduino作为车载控制器,结合ESP32或SIM模块进行通信。或者使用现有的物联网平台,比如阿里云IoT,来简化开发流程。 最后,应该提醒用户实际应用中可能遇到的挑战,比如通信延迟、信号稳定性、电源管理等,这些都需要在方案设计中充分考虑。</think>### 车辆远程控制技术方案及实现方式 #### 一、核心模块组成 1. **控制端** - 手机APP/Web界面:通过触控或虚拟摇杆发送控制指令,支持实时视频回传[^1] - 物理遥控器:专用硬件设备,提供低延迟操控 - 示例代码结构: ```python # 虚拟摇杆数据转换示例 def joystick_to_command(x, y): speed = y * MAX_SPEED steering = x * MAX_ANGLE return f"SPEED:{speed},STEER:{steering}" ``` 2. **通信系统** - 短距离方案: $$ R_{max} = \sqrt[4]{\frac{P_t G_t G_r \lambda^2}{(4\pi)^2 L}} $$ 使用Wi-Fi 6(理论速率9.6Gbps)或蓝牙5.3(有效距离300米) - 长距离方案: 4G/5G模块(CAT-M1/NB-IoT),时延可控制在50-100ms 卫星通信(海事/越野场景) 3. **车载控制单元(VCU)** - 硬件架构: ```mermaid graph TD A[通信模块] --> B{主控制器} B --> C[电机驱动] B --> D[转向舵机] B --> E[传感器融合] ``` - 控制算法实现: $$ \theta_{target} = K_p \cdot e(t) + K_i \int_{0}^{t} e(\tau)d\tau + K_d \frac{de(t)}{dt} $$ #### 二、关键技术实现 1. **实时视频传输** - 采用H.265编码压缩(相比H.264节省50%带宽) - 自适应码率控制算法: $$ R(t) = R_{base} + \alpha \cdot (1 - \frac{q_{current}}{q_{target}}) $$ 2. **故障安全机制** - 三级保护策略: 1. 信号丢失自动刹车(超时阈值可设) 2. 姿态传感器触发紧急停止(倾斜角>30°) 3. 独立看门狗电路 3. **能源管理** - 动态电源分配算法: $$ P_{alloc} = \begin{cases} 0.7P_{total} & \text{运动模式} \\ 0.3P_{total} & \text{待机模式} \end{cases} $$ #### 三、典型方案对比 | 方案类型 | 成本 | 时延 | 适用场景 | 开发难度 | |---------|------|------|----------|----------| | 4G+STM32 | ¥800 | 80ms | 城市巡检 | ★★☆ | | WiFi+ESP32 | ¥300 | 20ms | 室内物流 | ★☆☆ | | 卫星+工控机 | ¥15k | 500ms | 远洋船舶 | ★★★★ | #### 四、实施步骤 1. 搭建硬件原型(建议使用树莓派+Arduino组合) 2. 开发基础通信协议(建议MQTT+Protobuf) 3. 实现传感器数据融合(IMU+GPS+超声波) 4. 设计控制策略(建议先实现开环控制再升级PID) 5. 进行场地测试(注意电磁兼容性测试)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值