esp32-使用UDP控制电机(七)

目录

前言

端口配置

代码


前言

本文基于esp32使用platformio平台,通过udp来控制电机运行。

关键词:platformio,freertos,upd,esp32,motor,

端口配置

采用drv8833驱动板,其中esp32的d25接in2,d26接in1,d13接in4,d12接in3,esp32的3v3接drv8833的vcc,esp32的GND接drv8833的GND,2个电机的正负极接drv8833的OUT1至4。

代码

电机motor.h和motor.cpp代码如下

#ifndef MOTOR_H_
#define MOTOR_H_

#include <stdint.h>


class Motor
{
public:
	Motor(int inv);
	~Motor();

	void initialize(int pin_A, int pwm_channel_A, int pin_B, int pwm_channel_B);
	void setPwmDuty(float duty);

private:

	double frequency = 1000;
	uint8_t resolution_bits = 10;

	int pin_A;
	int pin_B;

	int pwm_channel_A;
	int pwm_channel_B;

	int inverse;

};

#endif
#include "Motor.h"
#include <Arduino.h>
#include <esp32-hal-ledc.h>


void Motor::initialize(int pin_A, int pwm_channel_A, int pin_B, int pwm_channel_B)
{
	this->pin_A = pin_A;
	this->pin_B = pin_B;
	this->pwm_channel_A = pwm_channel_A;
	this->pwm_channel_B = pwm_channel_B;

	ledcSetup(pwm_channel_A, frequency, resolution_bits);
	ledcAttachPin(pin_A, pwm_channel_A);
	ledcSetup(pwm_channel_B, frequency, resolution_bits);
	ledcAttachPin(pin_B, pwm_channel_B);
}

void Motor::setPwmDuty(float duty)
{
	duty = constrain(inverse * duty, -1, 1);

	if (duty > 0)
	{
		ledcWrite(this->pwm_channel_A, (int)(1000* duty));
		ledcWrite(this->pwm_channel_B, 0);
	}
	else
	{
		ledcWrite(this->pwm_channel_B, (int)(1000 * -duty));
		ledcWrite(this->pwm_channel_A, 0);
	}

}


Motor::Motor(int inv): inverse(inv)
{
}

Motor::~Motor()
{
}

main函数如下

#include<Arduino.h>
#include "motor.h"
#include<WiFi.h>
Motor * motorFL = new Motor(1);

Motor *motorFR = new Motor(1);
const char *ssid = "PDCN";
const char *password = "1234567890";
WiFiUDP udp;
int recv_length;
char recvbuff[255];       // 存储接收到的数据
uint16_t udp_port = 1234; // 端口号,ESP32默认IP:192.168.4.1
void motorTask(void *param){
    int recv_length;
    while (1)
    {
        recv_length = udp.parsePacket(); // 获取接收的数据的长度
        //Serial.println("recvlength:" + recv_length);
        if (recv_length) // 如果有数据那么recv_length不为0
        {
            int len = udp.read(recvbuff, 255); // 读取数据到recvbuff中
            if (len > 0)
            {
                int a = atoi(recvbuff);

                Serial.println(recvbuff); // 串口打印网口收到的数据
                switch (a)
                {
                case 1 /* constant-expression */:
                    /* code */
                    motorFL->setPwmDuty(1);
                    break;
                case 2:
                    motorFL->setPwmDuty(-1);
                    break;
                case 0:
                    motorFL->setPwmDuty(0);
                default:
                    break;
                }
                vTaskDelay(100);
                motorFL->setPwmDuty(0);
            }

            // 将接收到的数据发送回去
            udp.beginPacket(udp.remoteIP(), udp.remotePort()); // 准备发送数据到目标IP和目标端口
            udp.print("Receive:");
            udp.println(recvbuff); // 数据放入发送的缓冲区
            udp.endPacket();       // 发送

            for (int i = 0; i < 255; i++) // 清空接收数组
            {
                recvbuff[i] = 0;
            }
        }
        vTaskDelay(100);
    }
}
void setup(){
    Serial.begin(115200);

    WiFi.begin(ssid, password);
    Serial.println("正在连接到WiFi...");

    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.print("已连接到 ");
    Serial.println(ssid);
    Serial.print("IP地址:");
    Serial.println(WiFi.localIP());
    Serial.println(udp_port);

    udp.begin(udp_port); // 启动UDP监听端口,等待电脑发送数据
    Serial.println("Ready!");

    motorFL->initialize(25, 8, 26, 9);//PWM通道8和9,对应esp32的d25和d26
    motorFR->initialize(12, 10, 13, 11);//PWM通道的10和11,对应esp32的d12和d13
    //motorFL->setPwmDuty(0.5);
    xTaskCreatePinnedToCore(motorTask,"motorTask",8192,NULL,1,NULL,1);
}


void loop()
{
    // Do nothing. Everything is done in another task by the web server
    //motorFL->setPwmDuty(1);
    //motorFR->setPwmDuty(1);
}

实验通过电脑端串口调试器,如下所示,通过发送数字1或2使得电机运转0.1秒。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/621369.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA buid一直不能完成,无法运行

问题如下所示&#xff1a; 解决方案 output 路径不对&#xff0c;正确路径&#xff1a;项目目录\target\classes

【JAVA入门】Day04 - 方法

【JAVA入门】Day04 - 方法 文章目录 【JAVA入门】Day04 - 方法一、方法的格式1.1 无参无返回值的方法定义和调用1.2 带参数的方法定义和调用1.3 形参和实参1.4 带返回值的方法定义和调用1.5 方法的注意事项 二、方法的重载三、方法的使用四、方法的内存原理4.1 方法调用的基本内…

3W 3KVAC隔离 宽电压输入 AC/DC 电源模块——TP03AL系列

TP03AL系列产品具有交直流两用、输入电压范围宽、高可靠性、低功耗、安全隔离等优点。广泛适用于工控和电力仪器仪表、智能家居等对体积要求苛刻、并对EMC 要求不高的场合&#xff0c;如果需要应用于电磁兼容恶劣的环境下必须添加EMC 外围电路。

保研机试之【x86/x86-64体系结构中的寄存器】

先来看一下这六个选项的功能&#xff1a; 举一个例子&#xff1a; 对于CR2寄存器和中断向量表&#xff1a; 也就是先通过CR2寄存器找到引发错误的虚拟地址&#xff0c;然后操作系统分析错误原因&#xff0c;通过IDTR寄存器找到IDT&#xff08;中断向量表&#xff09;&#xff0…

Rust 中的mod 使用

1、本文将展示在Rust语言中如何引入模块。 2、项目目录如下图。 2.1、mod.rs中是需要引入的模块代码。 2.2、main.rs和文件夹utils在src文件夹下。 2.3、mod.rs代码如下。 pub mod nation{pub mod government{pub fn govern(){let aString::from("govern");println…

代码随想录算法训练营Day 38| 动态规划part01 | 理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

代码随想录算法训练营Day 38| 动态规划part01 | 理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯 文章目录 代码随想录算法训练营Day 38| 动态规划part01 | 理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯理论基础一、常规题目二、解题步骤…

代码随想录算法训练营第二十七天|​回溯法理论基础​、第77题. 组合

理论基础 回溯法基本介绍 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。 回溯是递归的副产品&#xff0c;只要有递归就会有回溯。递归函数的下面就是回溯的逻辑 因为回溯的本质是穷举&#xff0c;穷举所有可能&#xff08;暴力法&#xff09;&#xff0c;然…

Today At Apple 2024.04.15 Phone15 入门

官网&#xff1a; https://www.apple.com/today/Apple 亚洲第一大商店&#xff1a;Apple 静安零售店现已在上海开幕如下预约课程&#xff1a;下载 Apple Store&#xff08;不是app store&#xff09;&#xff0c;点击课程预约笔记&#xff1a;Today At Apple Notes果粉加群 &am…

并发编程总结(二)

目录 Java 对象头 wait / notify sleep(long n) 和 wait(long n) 的区别 死锁 定位死锁 饥饿 ReentrantLock Java 对象头 以 32 位虚拟机为例 64 位虚拟机 Mark Word 在程序中查看对象结构&#xff1a; 导入依赖&#xff1a; <!-- https://mvnrepository.com/artifac…

掌握这个Jenkins插件,离测试开发又近一步!

Jenkins Pipeline是一种可编程的、可扩展的持续交付管道&#xff0c;允许您使用脚本来定义整个软件交付过程。 以下是使用Jenkins Pipeline创建和配置流水线的基本步骤。 Part 01. 创建一个Pipeline Job 在Jenkins中创建一个新的"Pipeline"类型的Job。 以下是在J…

解决宝塔Nginx和phpMyAdmin配置端口冲突问题

问题描述 在对基于宝塔面板的 Nginx 配置文件进行端口修改时&#xff0c;我注意到 phpMyAdmin 的端口配置似乎也随之发生了变化&#xff01; 解决方法 官方建议在处理 Nginx 配置时&#xff0c;应避免直接修改默认的配置文件&#xff0c;以确保系统的稳定性和简化后续的维护…

简单问题汇总

一、vector和list 1.vector vector是可变大小数组的序列容器&#xff0c;拥有一段连续的内存空间&#xff0c;并且起始地址不变&#xff0c;因此能高效的进行随机存取&#xff0c;时间复杂度为o(1)&#xff1b;但因为内存空间是连续的&#xff0c;所以在进行插入和删除操作时…

触摸OpenNJet,云原生世界触手可及

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 文章目录 导言OpenNJet云原生引擎介绍云原生平台的介绍优化与创新 为什么选择OpenNJet云原生引擎如何在windo…

【MATLAB源码-第207期】基于matlab的单相光伏并网系统仿真,并网策略采用基于扰动观测法的MPPT模型和使用电压电流双闭环SPWM控制。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 本文将重点分析光伏发电最大功率点跟踪&#xff08;MPPT&#xff09;技术和逆变器的并网控制技术&#xff0c;并在Simulink环境下建立模拟系统&#xff0c;以体现这些技术的应用与效果。文章结构如下&#xff1a;首先简介光伏…

class常量池、运行时常量池和字符串常量池的关系

类常量池、运行时常量池和字符串常量池这三种常量池&#xff0c;在Java中扮演着不同但又相互关联的角色。理解它们之间的关系&#xff0c;有助于深入理解Java虚拟机&#xff08;JVM&#xff09;的内部工作机制&#xff0c;尤其是在类加载、内存分配和字符串处理方面。 类常量池…

【java9】java9新特性概述

经过4次的跳票&#xff0c;历经曲折的Java9最终在2017年9月21日发布。因为里面加入的模块化系统&#xff0c;在最初设想的时候并没有想过那么复杂&#xff0c;花费的时间超出预估时间。距离java8大约三年时间。 Java9提供了超过150项新功能特性&#xff0c;包括备受期待的模块…

sql注入---sqli靶场

1.什么是SQL注入 SQL注入是比较常见的网络攻击方式之一&#xff0c;它不是利用操作系统的BUG来实现攻击&#xff0c;而是针对程序员编写时的疏忽&#xff0c;通过SQL语句&#xff0c;实现无账号登录&#xff0c;甚至篡改数据库 2.sql注入原理 攻击者注入一段包含注释符的SQL语…

软件2班20240513

第三次作业 package com.yanyu;import java.sql.*; import java.util.ResourceBundle;public class JDBCTest01 {public static void main(String[] args) {ResourceBundle bundle ResourceBundle.getBundle("com/resources/db");// ctrl alt vString driver …

WebSocket建立网络连接——小案例

WebSocket是一种实现全双工通信的网络技术标准&#xff0c;它允许在用户的浏览器和服务器之间进行持久的、双向的通信。以下是对WebSocket的具体介绍&#xff1a; 实时性&#xff1a;与传统HTTP请求相比&#xff0c;WebSocket提供了更高效的实时数据交换方式。一旦建立连接&am…

极限基本思想

极限基本思想 在高等数学中极限是微积分的前置思想&#xff0c;没有极限的概念&#xff0c;那么微积分的理论将不复存在。极限也用于分析一个函数的连续性&#xff0c;可以说理解极限后理解函数的连续问题是轻而易举的事情。对于函数的连续性&#xff0c;不是什么高深的词汇就…