我想实现的是,我用电脑在串口监视器上输入一个字符串,arduino能识别这个字符串中的每一个字符并在相应的串口上给出相应的高低电平以驱动舵机,比如输入L1,RS,功能是左手腕舵机逆时针旋转90°,然后右手指舵机松开魔方,鉴于arduino的Serial.read()函数一次只能从串口上读取一个字节,所以要想输入字符串,得先写读入字符串程序。网上这种程序有,复制粘贴一段:String comdata = "";
void setup()
{
    Serial.begin(9600);
}
void loop()
{
    while (Serial.available() > 0) 
    {
        comdata += char(Serial.read());
        delay(2);
    }
    if (comdata.length() > 0)
    {
        Serial.println(comdata);
        comdata = "";
    }
}此代码作用就是用Serial.read()以此读入数据,然后存在comdata字符串内,之后要调用只需要comdata[x](x为你指定的整型数字)即可,但是我加进我的程序之后,发现问题并不这么简单,怎么调都出问题,在无能为力的情况下,只能重新写程序,一点一点研究走。我自己重写了一个程序,用于研究。

首先,我认为问题出在串口上面,arduino的串口一次通过一个值,如果不通过电脑给arduino输出的话,它应该会通过一个默认值。写入程序,发现这个默认值为-1

那么我们就需要一个判断语句,把这些没用的值过滤掉。if(myinput > 0)即可。这里注意,Serial.read()语句调用一次读一个字符,调用第二次就读下一个字符,所以我们需要一个临时的变量存储Serial.read()读到的值,问题是,该用什么类型定义这个变量呢?int myinput;然后 myinput = Serial.read(); 为啥?这里重要的事情说三遍:Serial.read()从电脑端读入的值强制转换成整型输出!Serial.read()从电脑端读入的值强制转换成整型输出!Serial.read()从电脑端读入的值强制转换成整型输出!但是,你从电脑端输入的是字符型;你从电脑端输入的是字符型;你从电脑端输入的是字符型;也就是说,你要输入1,myinput就是1字符的ASC2码,就是49,输入2,myinput就是整型50,输入S,返回的就是83!所以,要把myinput减一个‘0’,让他变成整形数字,这样的话,1为1,2为2,S就是35。明白了这个,之后的操作才可行。

输入123JS,成功!不过串口默认值变成-4。

当然你也可以用char来处理,不过默认值就变成了不知道什么的字符,看着很难受。

解决的这个问题后,来解决下一个问题,如果我在电脑上输入两个字符LS,存进两个myinput里,但是机器怎么识别是不是有默认值混进来呢,因为电脑不传命令,就传默认值,所以到头来,我的myinput可能是-1L,或是S-1,这就不好了。没有关系,加入这段代码即可//判断输入指令  if(myinput1 > 0)  {    order1 = myinput1 - '0';    order2 = myinput2 - '0';  }  else  {    order1 = myinput2 - '0';    order2 = myinput3 - '0';   }意思是,从串口里读入三个信号,然后从中依次判别各个信号是否有效(是否大于0),最后输出有效字符,存入order内,从而剔除了默认值-1。串口的问题已解决,之后的问题都迎刃而解,程序一下次就实验成功了。下面给出arduino源码//arduino环境#include <string.h>int servopinL1=9;//定义数字接口9 连接左手旋转伺服舵机信号线int servopinL2=10;//定义数字接口10 连接左手夹持伺服舵机信号线int servopinR1=8;//定义数字接口9 连接右手旋转伺服舵机信号线int servopinR2=7;//定义数字接口10 连接右手夹持伺服舵机信号线int myinput1;int myinput2;int myinput3;int order1;int order2;int myangle;//定义角度变量int pulsewidth;//定义脉宽变量int val;String comdata = "";void servopulse(int servopin,int myangle)//定义一个脉冲函数{pulsewidth=(myangle*11)+500;//将角度转化为500-2480 的脉宽值digitalWrite(servopin,HIGH);//将舵机接口电平至高delayMicroseconds(pulsewidth);//延时脉宽值的微秒数digitalWrite(servopin,LOW);//将舵机接口电平至低delay(20-pulsewidth/1000);}void setup(){  Serial.begin(9600);//连接到串行端口,波特率为9600  Serial.println("servo1 ready" ) ;  Serial.println("servo2 ready" ) ;    pinMode(servopinL1,OUTPUT);//设定舵机接口为输出接口  pinMode(servopinL2,OUTPUT);//设定舵机接口为输出接口  pinMode(servopinR1,OUTPUT);//设定舵机接口为输出接口  pinMode(servopinR2,OUTPUT);//设定舵机接口为输出接口}void loop(){  myinput1 = Serial.read();  myinput2 = Serial.read();  myinput3 = Serial.read();  Serial.println(myinput1);  Serial.println(myinput2);  Serial.println(myinput3);  delay(1000);    //判断输入指令  if(myinput1 > 0)    if(myinput2 > '0')    {       order1 = myinput1 - '0';       order2 = myinput2 - '0';           }  else  {    order1 = myinput2 - '0';    order2 = myinput3 - '0';  }    if(order1 > 0 && order2 > 0)  {  Serial.println(order1);  Serial.println(order2); if(order1 == 28) {  switch (order2)  {    case 1:          val = 0;      val=val*(180/2);//将数字转化为角度      Serial.print("anticlockwise ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinL1,val);//引用脉冲函数      }     break;             case 2:          val = 1;      val=val*(180/2);//将数字转化为角度      Serial.print("no move ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinL1,val);//引用脉冲函数      }    break;            case 3:          val = 2;      val=val*(180/2);//将数字转化为角度      Serial.print("clockwise ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinL1,val);//引用脉冲函数      }     break;         case 26:       //字符串'J'的ASC二码转化为整形后 - '0'          val = 4;      val=val*(180/9);//将数字转化为角度      Serial.print("close ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinL2,val);//引用脉冲函数      }     break;         case 35:       //字符串'S'的ASC二码转化为整形后 - '0'          val = 2;      val=val*(180/9);//将数字转化为角度      Serial.print("open ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinL2,val);//引用脉冲函数      }     break;        }  Serial.println("Good job!");  myinput1 = 0;  myinput2 = 0;  myinput3 = 0;  order1 = 0;  order2 = 0;  }  else if(order1 == 34)  {      switch (order2)  {    case 1:          val = 0;      val=val*(180/2);//将数字转化为角度      Serial.print("anticlockwise ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinR1,val);//引用脉冲函数      }     break;             case 2:          val = 1;      val=val*(180/2);//将数字转化为角度      Serial.print("no move ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinR1,val);//引用脉冲函数      }    break;            case 3:          val = 2;      val=val*(180/2);//将数字转化为角度      Serial.print("clockwise ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinR1,val);//引用脉冲函数      }     break;         case 26:       //字符串'J'的ASC二码转化为整形后 - '0'          val = 5;      val=val*(180/9);//将数字转化为角度      Serial.print("close ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinR2,val);//引用脉冲函数      }     break;         case 35:       //字符串'S'的ASC二码转化为整形后 - '0'          val = 0;      val=val*(180/9);//将数字转化为角度      Serial.print("open ");      Serial.print(val,DEC);      Serial.println();      for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度      {        servopulse(servopinR2,val);//引用脉冲函数      }     break;        }  Serial.println("Good job!");  myinput1 = 0;  myinput2 = 0;  myinput3 = 0;  order1 = 0;  order2 = 0;  }  }  }
---------------------

来源:CSDN
原文:https://blog.csdn.net/qq_26371477/article/details/79397613

arduino通信问题的学习与解决的更多相关文章

  1. 基于51单片机IIC通信的PCF8591学习笔记

    引言 PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入.一个输出和一个串行I2C 总线接口.3 个地址引脚A0.A1 和A2 用于编程硬件地址,允许将最多8 个器件连接 ...

  2. MindSpore联邦学习框架解决行业级难题

    内容来源:华为开发者大会2021 HMS Core 6 AI技术论坛,主题演讲<MindSpore联邦学习框架解决隐私合规下的数据孤岛问题>. 演讲嘉宾:华为MindSpore联邦学习工程 ...

  3. 【IScroll深入学习】解决IScroll疑难杂症

    前言 在去年,我们对IScroll的源码进行了学习,并且分离出了一段代码自己使用,在使用学习过程中发现几个致命问题: ① 光标移位 ② 文本框找不到(先让文本框获取焦点,再滑动一下,输入文字便可重现) ...

  4. 清晰易懂TCP通信原理解析(附demo、简易TCP通信库源码、解决沾包问题等)C#版

    目录 说明 TCP与UDP通信的特点 TCP中的沾包现象 自定义应用层协议 TCPLibrary通信库介绍 Demo演示 未完成功能 源码下载 说明 我前面博客中有多篇文章讲到了.NET中的网络编程, ...

  5. win7下Arduino Mega 2560驱动安装失败解决办法

    因为玩四轴用的apm的飞控板,而其需要安装此驱动,曾经在win8使用其,但是因为win8有相对应的数字证书保护措施(应该是这样的,因为好久了记不清楚了),以至于我每次都需要长按shift重启电脑关闭此 ...

  6. ORA-03113:通信通道的文件结尾解决

    今天跟往常一样,登陆PL/SQL,确登陆失败,出现一个错误“ORA-01034”和“ORA-27101”如图: 然后就就通过命令提示符去登陆Oracle,去查看怎么回事,然后问题进一步出现,错误“OR ...

  7. PC-PC-单片机(Arduino)通信实例

    请仔细理解相关参数,如端口设置.IP设置.COM口设置......等等.....不要盲目COPY.....这涉及2台电脑和一个单片机,其中一台电脑作为服务器并与单片机相连,负责通过网络与客户端通信(s ...

  8. 自学了三天的SeaJs学习,解决了前端的一些问题,与小伙伴们一起分享一下!

    我为什么学习SeaJs? [第一]:为了解决项目中资源文件版本号的问题,以及打包压缩合并等问题. [第二]:好奇心和求知欲.[我发现很多知名网站也都在使用(qq空间, msn, 淘宝等等),而且 Se ...

  9. 基于51单片机IIC通信的AT24C02学习笔记

    引言 最近在学习几种串行通信协议,感觉收获很多,这篇文章是学习IIC总线协议的第一篇文章,以后还会再写一篇关于PCF8591 IIC通信的ADDA转换芯片的文章. 关于IIC总线 IIC 即Inter ...

随机推荐

  1. H.264 中的Annex B格式和AVCC格式

    首先要理解的是没有标准的H.264基本流格式.文档中的确包含了一个Annex,特别是描述了一种可能的格式Annex B格式,但是这个并不是一个必须要求的格式.标准文档中指定了视频怎样编码成独立的包,但 ...

  2. DRF项目之层级关系

    一共分为四层关系. 第一层:视图 用来接收前端传递的参数,并实现业务逻辑相关的数据处理,并将数据通过创建序列化器对象的形式传递给序列化器. 第二层:序列化器 接收前端传递的数据,并将数据进行序列化操作 ...

  3. Python爬虫教程-爬取5K分辨率超清唯美壁纸源码

    简介 壁纸的选择其实很大程度上能看出电脑主人的内心世界,有的人喜欢风景,有的人喜欢星空,有的人喜欢美女,有的人喜欢动物.然而,终究有一天你已经产生审美疲劳了,但你下定决定要换壁纸的时候,又发现网上的壁 ...

  4. 使用 JvisualVM 监控 spark executor

    使用 JvisualVM,需要先配置 java 的启动参数 jmx 正常情况下,如下配置 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmx ...

  5. ping命令工具:同时ping多个IP

    检测多个ip在同一时间点的响应状态,通过对比来判断哪个ip异常. 下载地址:https://share.weiyun.com/5XCkypG

  6. Scrapy 中的 Request 对象和 Respionse 对象

    1.Request 对象 Request 对象用来描述一个 HTTP 请求,下面是其构造方法的参数列表 Request(url, [, callback, method='Get', headers, ...

  7. 吴裕雄--天生自然PYTHON爬虫:爬虫攻防战

    我们在开发者模式下不仅可以找到URL.Form Data,还可以在Request headers 中构造浏览器的请求头,封装自己.服务器识别浏览器访问的方法就是判断keywor是否为Request h ...

  8. 一、什么是Velocity及简单示例

    1.velocity简介:    velocity是一个java模板引擎技术,任何人可以使用这种简单而又强有力的模板语言去获取java对象. 在使用Velocity进行web开发时,web开发人员和j ...

  9. 使用IDEA,Eclispe搭建Spring Boot项目

    如何创建一个Spring Boot项目?这里使用maven来进行依赖管理,根据常用的IDE,可以使用IDEA.Eclipse.或者访问官方网站搭建. 项目搭建环境准备 JDK:1.8 MAVEN:3. ...

  10. mabatis--查询缓存

    1.mybatis提供查询缓存,用于减轻数据库压力,提高数据库性能. 2.mybatis提供一级缓存.二级缓存: 3.一级缓存是SqlSession级别的缓存.在SqlSession对象中,存在一个数 ...