极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 21221|回复: 13

舵机控制

[复制链接]
发表于 2016-4-11 20:10:00 | 显示全部楼层 |阅读模式
求各位大神帮忙,如何利用串口控制舵机转动,即是串口输入需要转的角度,如输入36,舵机转36度,求代码
回复

使用道具 举报

 楼主| 发表于 2016-4-11 20:50:08 | 显示全部楼层
为什么这样子不能实现功能


#include <Servo.h>
Servo myservo;  
void setup()
{
  Serial.begin(9600);
  Serial.print("ready!");
  myservo.attach(11);  
}
void loop()
{
   static int pos=0;
  if(Serial.available())
  {
    char ch = Serial.read();   //读取串口数据
    delay(20);
     pos=ch-'0';
     myservo.write(pos);
   }
  delay(15);            
}
回复 支持 反对

使用道具 举报

发表于 2016-4-12 00:45:42 | 显示全部楼层
发的是数字36,用不着-‘0’。这个'0'是个ascii码,减掉就不对了。
回复 支持 反对

使用道具 举报

发表于 2016-4-12 12:02:34 | 显示全部楼层
seagatecm 发表于 2016-4-12 00:45
发的是数字36,用不着-‘0’。这个'0'是个ascii码,减掉就不对了。

減是有點錯, 不能處理所有情況, 但不減就是全完的錯.

減了最少在 0-9 度時是對的, 不減就完全不對了.
回复 支持 反对

使用道具 举报

发表于 2016-4-12 12:06:10 | 显示全部楼层
FrankyShen 发表于 2016-4-11 20:50
为什么这样子不能实现功能

從你加入 pos=ch-'0'; , 可見你或許應該知道 myservo.write(pos), 當中 pos 是一個數值.
問題在於 ch-'0' 的做法, 只可以處理 '0' - '9' 個位數字的輸入.
如果輸入了 '10', 你會先收到一個 '1', 之後一個 '0', 結果就變成先轉去 1 度, 再轉去 0 度的位置.

你要處理的, 不是輸出的問題, 而是如何把 serial 中輸入的數字, 轉成相對的數值.
方法有很多, 找找吧, 不會太難的, 這可說是從 serial 輸入數值的基本吧.
回复 支持 反对

使用道具 举报

发表于 2016-4-12 16:00:59 | 显示全部楼层
Super169 发表于 2016-4-12 12:06
從你加入 pos=ch-'0'; , 可見你或許應該知道 myservo.write(pos), 當中 pos 是一個數值.
問題在於 ch-'0 ...

串口通讯,或者是IIC通讯,都会存在这种问题(我目前也处于迷迷糊糊的状态中。。。)
Super169,大神,方便的话,能不能帮开个教学贴?
关于: Arduino to Arduino    PC to Arduino 这两种情况时,
1.Arduino 1#发送数据,Arduino2#收到数据,转动舵机到相应角度,或模拟引脚输出对应占空比。
                                 Arduino2#返回数据,Arduino1#显示出2#发回来的角度值,或亮度值。
2.PC to Arduino........
多谢。
(这会是一个关于Serial.write,Serial.read,char,int,bit,byte等等的故事,期待ing)
回复 支持 反对

使用道具 举报

发表于 2016-4-12 16:38:49 | 显示全部楼层
串口接收到是char ,然后需要不断检测去接收,接收到的要自动转换成int,
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-4-12 21:02:26 | 显示全部楼层
Super169 发表于 2016-4-12 12:06
從你加入 pos=ch-'0'; , 可見你或許應該知道 myservo.write(pos), 當中 pos 是一個數值.
問題在於 ch-'0 ...

嗯,问题在于“如何把 serial 中輸入的數字, 轉成相對的數值”,可是找了很多了,还是解决不了
其中

#include <Servo.h>
Servo myservo;  
int pos;

void setup()
{
  Serial.begin(9600);
  Serial.print("ready!");
  myservo.attach(11);  
}
void loop()
{
  //static int pos=0;

  if(Serial.available()>=1)
  {   
    pos=Serial.parseInt();
    delay(10);   
    Serial.println(pos);  
    // myservo.write(pos);
   }
    myservo.write(pos);
  delay(15);            
}

这个程序好像可以识别数字,但是为什么每次输入一个角度后会自动回复零
输入36然后会print 36,但是之后自动print一个0
回复 支持 反对

使用道具 举报

发表于 2016-4-12 23:31:23 | 显示全部楼层
你说的是手工输入36啊,那是ascii的‘3’‘6‘。你可以直接发送4个Byte的36。接收后用parseInt强转。就是俗称二进制发送。
如果你一定想发ascii的字符,那就弄个数组存下来,读完后顺序加在一起

伪代码如下
char buf[4]; // 不会超过360度3个字符
int len = 0;

while(Serial.available())
{
    char ch = Serial.read();   
    buf[len] = ch - '0';
    len ++;
}

int Pow(int n)
{
   int v = 1;
   for (int i = 1; i < n; n++)
      v *= 10;
   return v;
}
int angle = 0;
// 这数组里面就是十进制数了,+在一起
for (int i = 0; i < len; i++)
{
   angle += buf[i] * Pow(len - i);
}

这代码没调过,大概是这意思。
回复 支持 反对

使用道具 举报

发表于 2016-4-13 11:58:59 | 显示全部楼层
wwwusr 发表于 2016-4-12 16:00
串口通讯,或者是IIC通讯,都会存在这种问题(我目前也处于迷迷糊糊的状态中。。。)
Super169,大神,方便 ...

通訊在於雙方的協定, 並沒有一定的準則.  只要 發出 跟 接收 的一方, 同相同的協定就可以.

比如說, 要傳送一個 10 的數值, 你可以用 Serial.print 以字符 "1" 及 "0", 接收後再轉回數值.
也可以用 Serial.write 直接發出.
最重要是雙方有共識, 用什麼方法也可以.  問題是你著重於速度, 安全度, 還是要容易給人看 (機械之間的通訊, 原本不需要考慮這點的, 但很多時都會選用這個).

我自己做的, 不會理會是否容易看, 全部以資料的原來的形式送出, 不論是 int, float, double, .... 都不會進行轉換, 直接以 byte 的形式發送.  

簡單的說, 要發送一個 float (相信最多人覺得有問題就是 float 的傳送吧), 四個 byte.  就用 byte pointer 把四個 byte 以 Serial.write 發出.  接收的一邊 以 Serial.Read 收到後, 一個個 byte 以 byte pointer 的形式放回 float 變數中.  不論 float, double, int, long, char[].... 只要知道要發送的數量, 都可以用這個方式發送.

這是最快最直接的方法, 過程有點複雜, 要了解每種 data type 的特性.  反正自己做的通訊, 雙邊都是自己做的, 有共同的協定就可以.

至於 PC 跟 arduino 通訊, 如果你指的是 serial monitor, 就只可以用 char[] 吧.  你在 PC 端輸入的是字符, 需要自已轉化成數值.  而 android 發出的, 在 PC 上看, arduino IDE 的 serial monitor 只可以顯示 ASCII, 如果用其他的, 可以顯示 HEX, 又或你自己寫個 PC 端, 就什麼也可以了.  因應你用的工具, 選擇所需的協定吧.
回复 支持 反对

使用道具 举报

发表于 2016-4-13 12:02:45 | 显示全部楼层
FrankyShen 发表于 2016-4-12 21:02
嗯,问题在于“如何把 serial 中輸入的數字, 轉成相對的數值”,可是找了很多了,还是解决不了
其中

在 if(Serial.available()) 之內, 如果你已完成一次輸入, 最後加上 while (Serial.available()) Serial.read(); 去清空吧.
回复 支持 反对

使用道具 举报

发表于 2016-4-13 12:08:48 | 显示全部楼层
本帖最后由 Super169 于 2016-4-13 23:04 编辑
seagatecm 发表于 2016-4-12 23:31
你说的是手工输入36啊,那是ascii的‘3’‘6‘。你可以直接发送4个Byte的36。接收后用parseInt强转。就是俗 ...


這個方法可以簡化一點.
先用一個 long 接了第一個數字字符: ch - '0' 的值.
之後一直 read, 如果再有新的數字字符, 就把之前的 x10 再加上新的 ch - '0', 直到全部數字讀出來.

比如輸入 "123"
先接收了 "1" -> val = ch - '0'; -> val = 1
再接收了 "2" -> val = val * 10 + ch - '0' -> val = 12
再接收了 "3" -> val = val * 10 + ch - '0' -> val = 123
再沒有了, val = 123 就完了.

最後, 可以歸納成 以 0 開始, 然後一個個字符讀進來, 每讀取了一個放入 ch, 就用 val = val * 10 + ch - '0'  添加上去.
回复 支持 反对

使用道具 举报

发表于 2016-4-13 13:04:53 | 显示全部楼层
Super169 发表于 2016-4-13 11:58
通訊在於雙方的協定, 並沒有一定的準則.  只要 發出 跟 接收 的一方, 同相同的協定就可以.

比如說, 要 ...

EN, 谢谢!
回头静下来时,一定要系统的捋顺一下。
回复 支持 反对

使用道具 举报

发表于 2016-4-30 23:23:17 | 显示全部楼层
请注册Intorobot平台,www.intorobot.com里面有机械控制的例子,有相关参考程序如:
  1. /*
  2. ************************************************************************
  3. * @author  :  IntoRobot Team
  4. * @version :  V1.0.0
  5. * @date    :  03-30-15
  6. ************************************************************************
  7. This application example code is in the public domain.
  8. This example is modified from arduino example

  9. Sweep

  10. */


  11. Servo myservo;  // create servo object to control a servo
  12.                 // twelve servo objects can be created on most boards

  13. int pos = 0;    // variable to store the servo position

  14. void setup()
  15. {
  16.     myservo.attach(D9);  // attaches the servo on pin 9 to the servo object
  17. }

  18. void loop()
  19. {
  20.     for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
  21.     {                                  // in steps of 1 degree
  22.         myservo.write(pos);              // tell servo to go to position in variable 'pos'
  23.         delay(15);                       // waits 15ms for the servo to reach the position
  24.     }
  25.   
  26.     for(pos = 180; pos>=0; pos -= 1)     // goes from 180 degrees to 0 degrees
  27.     {                                
  28.         myservo.write(pos);              // tell servo to go to position in variable 'pos'
  29.         delay(15);                       // waits 15ms for the servo to reach the position
  30.     }
  31. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-5-20 19:57 , Processed in 0.049905 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表