Example: use raspberry pi 4 control multiple motors(tb660)

abstract

This is a project for controlling multiple motors by using joystick, the buttons’ information can be obtained from topic “/joystick”. We got the sensor’s signals from arduino, and sent the command from topic “joystick”.

raspberry pi code(python):

#!/usr/bin/env python3
from time import sleep
import time
import numpy as np
import rospy
import RPi.GPIO as GPIO
from sensor_msgs.msg import JointState
from multiprocessing import Process, Array, Value
import multiprocessingValveFront = 17
ValveRear = 27
enPinR = 13
directionpinR = 19
steppinR = 26
enPinL  = 16
directionpinL = 20
steppinL = 21
FORWARD = GPIO.HIGH
BACKWARD = GPIO.LOW
CLOCKWISE = GPIO.HIGH
COUNTERCLOCK = GPIO.LOW
stepsPerRevolution = 6400
OUTPUT = GPIO.OUT
# pin = 12lspeed = 100
rotateSpeed = 50rotationCountReader = Value("f",0)
linearCountReader = Value("f",0)
# msg_ = np.zeros((7,),np.float16)
msg_ = Array("f",[0,0,0,0,0,0,0,0,0,0,0,0,0,0])
lock = multiprocessing.Lock()def delayMicroseconds(sec):start = time.time()while (time.time()-start)*1000000 < sec:passdef setupBoard():GPIO.setmode(GPIO.BCM)# GPIO.setup(pin,GPIO.OUT)GPIO.setwarnings(False)GPIO.setup (ValveFront,OUTPUT)GPIO.setup(ValveRear,OUTPUT)GPIO.setup (directionpinR,OUTPUT)GPIO.setup (steppinR,OUTPUT)GPIO.setup(enPinR,OUTPUT)GPIO.setup (directionpinL,OUTPUT)GPIO.setup (steppinL,OUTPUT)GPIO.setup(enPinL,OUTPUT)GPIO.output(ValveFront,GPIO.LOW)GPIO.output(ValveRear,GPIO.LOW)GPIO.output(enPinR,GPIO.LOW)GPIO.output(enPinL,GPIO.LOW)def Lmotor(directionL:bool,dis:float):speed_m = 400.0/lspeedGPIO.output(directionpinL,directionL)for i in range(int(stepsPerRevolution*dis/6)): # stepsPerRevolution*dis/6GPIO.output (steppinL,GPIO.HIGH)delayMicroseconds(50)# sleep(0.005)GPIO.output (steppinL,GPIO.LOW)delayMicroseconds(50)if(directionL == FORWARD):linearCountReader.value = linearCountReader.value+1else:linearCountReader.value = linearCountReader.value-1# sleep(0.005)def LmotorD(directionL:bool):GPIO.output(directionpinL,directionL)for i in range(2): # stepsPerRevolution*dis/6GPIO.output (steppinL,GPIO.HIGH)delayMicroseconds(50)# sleep(0.005)GPIO.output (steppinL,GPIO.LOW)delayMicroseconds(50)if(directionL == FORWARD):linearCountReader.value = linearCountReader.value+1else:linearCountReader.value = linearCountReader.value-1def Rmotor(directionR = CLOCKWISE):GPIO.output(directionpinR,directionR)for i in range(int(stepsPerRevolution/4)):GPIO.output (steppinR,GPIO.HIGH)delayMicroseconds(rotateSpeed)# sleep(0.005)GPIO.output (steppinR,GPIO.LOW)delayMicroseconds(rotateSpeed)if(directionR == CLOCKWISE):rotationCountReader.value = rotationCountReader.value+1else:rotationCountReader.value = rotationCountReader.value-1# sleep(0.005)def RmotorD(directionR = CLOCKWISE):GPIO.output(directionpinR,directionR)for i in range(2):GPIO.output (steppinR,GPIO.HIGH)delayMicroseconds(rotateSpeed)# sleep(0.005)GPIO.output (steppinR,GPIO.LOW)delayMicroseconds(rotateSpeed)if(directionR == CLOCKWISE):rotationCountReader.value = rotationCountReader.value+1else:rotationCountReader.value = rotationCountReader.value-1def RotationThread():# global msg_while True:# print(stepsPerRevolution)if msg_[0] >= 1:print("rotating")Rmotor(CLOCKWISE)sleep(0.001)if msg_[0] == -1:print("counter rotating")Rmotor(COUNTERCLOCK)sleep(0.001)if msg_[5] > 50:RmotorD(CLOCKWISE)if msg_[5] < -50:RmotorD(COUNTERCLOCK)def LinearThread():while True:if msg_[4] >= 50:GPIO.output(ValveFront,GPIO.LOW)GPIO.output(ValveRear,GPIO.HIGH)sleep(0.02)Lmotor(BACKWARD,10)GPIO.output(ValveFront,GPIO.HIGH)GPIO.output(ValveRear,GPIO.LOW)sleep(0.02)Lmotor(FORWARD,10)print("moving")sleep(0.001)if msg_[4] <= -50:GPIO.output(ValveFront,GPIO.LOW)GPIO.output(ValveRear,GPIO.HIGH)sleep(0.02)Lmotor(FORWARD,10)GPIO.output(ValveFront,GPIO.HIGH)GPIO.output(ValveRear,GPIO.LOW)sleep(0.02)Lmotor(BACKWARD,10)print("back moving")sleep(0.001)if msg_[6] > 50:LmotorD(BACKWARD)if msg_[6] < -50:LmotorD(FORWARD)def doMsg(msg:JointState):for i in range(7):msg_[i] = msg.position[i]def ft_sub():rospy.init_node('mediator',anonymous=True)sub = rospy.Subscriber('joystick',JointState,doMsg,queue_size=10)rate = rospy.Rate(1000)while not rospy.is_shutdown():# print(msg_[0])print(linearCountReader.value)print(rotationCountReader.value)rate.sleep()if __name__=='__main__':try:setupBoard()a1 = Process(target=RotationThread)a2 = Process(target=LinearThread)a3 = Process(target=ft_sub)a1.start()a2.start()a3.start()a1.join()a2.join()a3.join()print("----------------")except KeyboardInterrupt:GPIO.cleanup()

arduino code:

#include <PS2X_lib.h>  //for v1.6
#include <ros.h>
#include <ros/time.h>
#include <std_msgs/Int8.h>
#include <sensor_msgs/JointState.h>#define PS2_DAT        A9  //14    
#define PS2_CMD        A10  //15
#define PS2_SEL        A11  //16
#define PS2_CLK        A12  //17#define pressures   false
#define rumble      falsePS2X ps2x; // create PS2 Controller Class
ros::NodeHandle node_handle;int error = 0;
byte type = 0;
byte vibrate = 0;// parameters for reading the joystick:
int range = 127;               // output range of X or Y movement
int responseDelay = 5;        // response delay of the mouse, in ms
int threshold = 2;      // resting threshold
int center = 127;         // resting position valuesensor_msgs::JointState msg;
std_msgs::Int8 msg_;
ros::Publisher pub("joystick", &msg);char* id = "/joint";
char *a[] = {"FL", "FR", "BR", "BL","BA","BC","BV","START","SELECT","CIRCLE","TRIAGNLE","SQUARE","CROSS","Z2"};
float pos[14];void setup(){node_handle.getHardware()->setBaud(57600);delay(300);  //added delay to give wireless ps2 module some time to startup, before configuring it//setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for errorerror = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);node_handle.initNode();node_handle.advertise(pub);msg.header.frame_id = id;msg.name_length = 14;msg.position_length = 14;msg.name= a;msg.position = pos;
}int x_ = 0;
int y_ = 0;
int z_ = 0;
int lx_ = 0;
int ly_ = 0;
int rx_ = 0;
int ry_ = 0;
bool start_ = 0;
int select_ = 0;
int circle_ = 0;
int triangle_ =0;
int square_ = 0;
int cross_ = 0;
int z2_ = 0;void loop() {if(error == 1) //skip loop if no controller foundreturn; ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speedif(ps2x.Button(PSB_PAD_LEFT)){// Serial.print("LEFT held this hard: ");// Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC);                  //-xx_ = -1;}else if(ps2x.Button(PSB_PAD_RIGHT)){// Serial.print("Right held this hard: ");// Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC);                 //+xx_ = 1;}else{x_ = 0;}if(ps2x.Button(PSB_PAD_UP)) {      //will be TRUE as long as button is pressed// Serial.print("Up held this hard: ");// Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);                    //-yy_ = -1;}else if(ps2x.Button(PSB_PAD_DOWN)){// Serial.print("DOWN held this hard: ");// Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);                  //+yy_ = +1;}  else{y_ = 0;}if(ps2x.Button(PSB_L2)){// Serial.println("L2 pressed");                                   //-zz_ = -1;}else if(ps2x.Button(PSB_L1)){// Serial.println("L1 pressed");                                   //+zz_ = +1;}else{z_ = 0;}if(ps2x.Button(PSB_R2)){// Serial.println("L2 pressed");                                   //-zz2_ = -1;}else if(ps2x.Button(PSB_R1)){// Serial.println("L1 pressed");                                   //+zz2_ = +1;}else{z2_ = 0;}vibrate = ps2x.Analog(PSAB_CROSS);  //this will set the large motor vibrate speed based on how hard you press the blue (X) buttonif (ps2x.NewButtonState()) {        //will be TRUE if any button changes state (on to off, or off to on)if(ps2x.Button(PSB_START)){         //will be TRUE as long as button is pressedSerial.println("Start is being held");start_ = !start_;}if(ps2x.Button(PSB_SELECT)){Serial.println("Select is being held"); select_ += 1;}if(ps2x.Button(PSB_CIRCLE)){               //will be TRUE if button was JUST pressedSerial.println("Circle just pressed");circle_ = 1;}else if(ps2x.ButtonReleased(PSB_CIRCLE))circle_ = 0;if(ps2x.Button(PSB_CROSS)){               //will be TRUE if button was JUST pressed OR releasedSerial.println("X just changed");cross_ = 1;}else if(ps2x.ButtonReleased(PSB_CROSS))cross_ = 0;if(ps2x.Button(PSB_SQUARE)){              //will be TRUE if button was JUST releasedSerial.println("Square just released");square_ = 1;}else if(ps2x.ButtonReleased(PSB_SQUARE))square_ = 0;     if(ps2x.Button(PSB_TRIANGLE)){Serial.println("Triangle pressed");triangle_ = 1; }  else if(ps2x.ButtonReleased(PSB_TRIANGLE))triangle_ = 0;   }lx_ = readAxis(PSS_LX);ly_ = readAxis(PSS_LY); rx_ = readAxis(PSS_RX);ry_ = readAxis(PSS_RY); // if(abs(rx_)>0)//     Serial.println(rx_, DEC);// if(abs(ry_)>0)//     Serial.println(ry_, DEC);//     Serial.println(x_, DEC); msg.position[0] = x_; msg.position[1] = y_; msg.position[2] = z_; msg.position[3] = lx_; msg.position[4] = ly_;msg.position[5] = rx_; msg.position[6] = ry_;msg.position[7] = start_;msg.position[8] = select_;msg.position[9] = circle_;msg.position[10] = triangle_;msg.position[11] = square_;msg.position[12] = cross_;msg.position[13] = z2_;// msg.header.stamp = ros::Time::now();pub.publish( &msg );node_handle.spinOnce();delay(25);  
}int readAxis(int thisAxis) { // read the analog input:int reading = ps2x.Analog(thisAxis);// map the reading from the analog input range to the output range:// reading = map(reading, 0, 255, 0, range);// if the output reading is outside from the// rest position threshold,  use it:int distance = reading - center;if (abs(distance) < threshold) {distance = 0;} // return the distance for this axis:return distance;
}

Reference

https://github.com/zouyuelin/colomagJoycontrol_ros/blob/master

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Docker容器中启用SSH服务,实现外部访问的详细教程

目录 步骤 1: 安装 SSH 服务器 步骤 2: 配置 SSH 服务器 步骤 3: 设置 SSH 用户 步骤 4: 重启 SSH 服务器 步骤 5: 映射容器端口 步骤 6: 使用 SSH 连接到容器 要在Docker容器中启用SSH服务&#xff0c;以便从外部访问&#xff0c;您需要执行以下步骤&#xff1a; 步骤 …

面试就是这么简单,offer拿到手软(三)—— 常见中间件框架面试题,es,redis,dubbo,zookeeper kafka 等

面试就是这么简单&#xff0c;offer拿到手软&#xff08;一&#xff09;—— 常见非技术问题回答思路 面试就是这么简单&#xff0c;offer拿到手软&#xff08;二&#xff09;—— 常见65道非技术面试问题 面试就是这么简单&#xff0c;offer拿到手软&#xff08;三&#xff…

python-ATM机

编写程序&#xff0c;实现一个具有开户、查询、取款、存款、转账、锁定、解锁、退出功能的银行管理系统。 结果展示 1.Main主方法 from zzjmxy.class7.atm import ATM from zzjmxy.class7.manager import Manager # 主面板&#xff0c;实现主要逻辑if __name__"__main__…

kubectl获取命名空间下所有configmap集合的方法

前言&#xff1a; 获取单个configmap并忽略特定字段的操作可参照&#xff1a;kubectl获取ConfigMap导出YAML时如何忽略某些字段。 要获取命名空间下所有ConfigMap并忽略特定字段&#xff0c;你可以使用kubectl命令与例如yq这样的工具结合使用来忽略或删除不需要的字段。以下是…

「实用场景教程」如何用日程控件DHTMLX Scheduler制作酒店预订日历?(三)

dhtmlxScheduler是一个类似于Google日历的JavaScript日程安排控件&#xff0c;日历事件通过Ajax动态加载&#xff0c;支持通过拖放功能调整事件日期和时间&#xff0c;事件可以按天&#xff0c;周&#xff0c;月三个种视图显示。 DHTMLX Scheduler正式版下载 在本教程中&…

t-SNE方法:

使用t-SNE时&#xff0c;除了指定你想要降维的维度&#xff08;参数n_components&#xff09;&#xff0c;另一个重要的参数是困惑度&#xff08;Perplexity&#xff0c;参数perplexity&#xff09; 困惑度&#xff1a; 困惑度大致表示如何在局部或者全局位面上平衡关注点&am…

音乐一拍到底多长

1.拍是什么 拍是一个描述音符的最小单位 2.BPM 拍速度 一分钟多少拍&#xff0c;每首个都有一个人为规定的拍速度 3.音符 对一个音要唱多长的定义&#xff0c;并且使用4分音符&#xff0c;8分音符进行更细化的分割 4.一拍到底有多长 首先拍类比物理学&#xff0c;他是一…

BearPi Std 板从入门到放弃 - 后天篇(2)(I2C1读写EEPROM)

简介 基于 BearPi Std 板从入门到放弃 - 后天篇&#xff08;1&#xff09;(I2C1 读取 光照强度)&#xff0c; 使用同一个I2C接口访问EEPROM, 同时读取光照亮度 主芯片: STM32L431RCT6 LED : PC13 \ 推挽输出即可 \ 高电平点亮 串口: Usart1 I2C : I2C1 光照强度传感器&#xf…

金蝶云星空和管易云接口打通对接实战

金蝶云星空和管易云接口打通对接实战 对接系统金蝶云星空 金蝶K/3Cloud结合当今先进管理理论和数十万家国内客户最佳应用实践&#xff0c;面向事业部制、多地点、多工厂等运营协同与管控型企业及集团公司&#xff0c;提供一个通用的ERP服务平台。K/3Cloud支持的协同应用包括但不…

算法通关村第十四关|青铜|堆结构

堆是将一组数据按照完全二叉树的存储顺序&#xff0c;将数据存储在一个一维数组中的结构。 大顶堆&#xff1a;任意节点的值均大于等于它的左右孩子&#xff0c;并且最大的值位于堆顶&#xff0c;即根节点处。 小顶堆&#xff1a;任意节点的值均小于等于它的左右孩子&#xff0…

记录 | CUDA编程中的 __host__ __device__ 双重修饰

通过 __host__ 和 __device__ 双重修饰符&#xff0c;可以把函数同时定义在 CPU 和 GPU 上&#xff0c;这样 CPU 和 GPU 都可以调用 比如&#xff1a; #include <cstdio> #include <cuda_runtime.h>__host__ __device__ void say_hello(){printf("Hello, w…

在python的Scikit-learn库中,可以使用train_test_split函数来划分训练集和测试集。

文章目录 一、在Scikit-learn库中&#xff0c;可以使用train_test_split函数来划分训练集和测试集总结 一、在Scikit-learn库中&#xff0c;可以使用train_test_split函数来划分训练集和测试集 在Scikit-learn库中&#xff0c;可以使用train_test_split函数来划分训练集和测试…

【yolov8】与yolov5的区别及改进详解

图像识别技术在物联网、智能监控等领域广泛应用。而深度学习中的目标检测技术&#xff0c;能够帮助我们对图像中的目标进行识别&#xff0c;进而实现自动化控制。目前&#xff0c;Yolov8和Yolov5是目标检测领域热门的模型。 yolo目标检测原理yolov5详解yolov8yolov8结构图Conv模…

智能优化算法应用:基于学校优化算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于学校优化算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于学校优化算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.学校优化算法4.实验参数设定5.算法结果6.参考…

追逐代码的梦,计算机行业的心路历程

标题&#xff1a;追逐代码的梦&#xff0c;计算机行业的心路历程 当初选择计算机行业&#xff0c;并非出于一时冲动&#xff0c;而是深深被数字的魔力所吸引。我笑着回答&#xff1a;“因为我梦想成为神奇的码农&#xff01;我想像编织魔法一样编写程序&#xff0c;创造出炫酷…

Linux中shell的运行原理

在Linux中&#xff0c;每次输入命令时&#xff0c;前面都会出现一串字母&#xff0c;我们称之为命令行提示符 实际上&#xff0c;命令行提示符是一种外壳程序 外壳程序的概念&#xff1a; 前面我们提到过&#xff0c;在Linux中&#xff0c;一切皆文件&#xff0c;所谓的命令就…

程序员的实用网站导航与推荐

当你遇到问题时 Stack Overflow&#xff1a;订阅他们的每周新闻和任何你感兴趣的主题Google&#xff1a;全球最大搜索引擎必应&#xff1a;在你无法使用Google的时候CSDN&#xff1a;聊胜于无AI导航一号AI导航二号 新闻篇 OSCHINA&#xff1a;中文开源技术交流社区 针对初学…

UE Windows平台下Linux的交叉编译项目打包

UE Windows平台下Linux的交叉编译项目打包 交叉编译&#xff08;Cross-compilation&#xff09; 使得在以Windows为中心的工作流程中工作的游戏开发者能够以Linux为目标对项目进行打包。目前&#xff0c;只有Windows支持交叉编译。 交叉编译支持的平台 Windows | Linux-x86_…

每日3道PWN(第二天)

ciscn_2019_n_1 参考&#xff1a; [BUUCTF-pwn]——ciscn_2019_n_1-CSDN博客 [BUUCTF]PWN5——ciscn_2019_n_1_ciscn_2019_n_4-CSDN博客 BUUCTF—ciscn_2019_n_1 1-CSDN博客 checksec一下 64位栈溢出 按f5查看main函数&#xff0c;双击可疑函数 发现含有命令执行的且发现fl…

SOCKET、TCP、HTTP之间的区别与联系

SOCKET、TCP、HTTP之间的区别与联系 一、 Socket 1、什么是socket2、为什么需要socket3、建立socket连接 二、HTTP(基于TCP) 1、HTTP的概念2、HTTP连接的特点 连接请求&#xff1a;一次连接连接请求&#xff1a;短连接(socket是长连接) 三、TCP/IP协议簇 四、HTTP、Socket…