请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

Nucleo + Scratch,给你孩子的编程玩具 精华  

[复制链接]
qianfan 发布时间:2015-6-8 19:09
本帖最后由 QianFan 于 2015-6-23 12:34 编辑 " k' |! ?6 t+ i8 e, r2 |
/ u. Y6 A& k; p0 X; |
    不知道大家有没有听说的Scratch: http://scratch.mit.edu/    是由麻省理工开发的一个软件,帮助孩子们从零开始学习编程。图形化的程序设计,萌萌哒的界面,想必能够吸引住众多孩子。不过这么好的软件貌似在国内知名度不高。
. {8 X/ f7 y0 x/ x, x! w5 W" ^ scartch.png
0 R, s4 f) e2 t7 d8 [' T    后来,一个团队开发了一个名为S4A(Scartch for Arduino)的软件:http://s4a.cat/   将Scartch与Arduino连接起来。结合了Scartch的编程优点,外加Arduino的众多传感器,一时间孩子们也能够玩转舵机,开关,以及模拟量的传感器了。S4A使用了Arduino的6路AD采集接口,3路PWM接口和3路舵机接口,方便小孩子连接传感器,实现自己的设计。
1 O8 S7 ~0 Z8 v* j7 ?) s scartch.png
, m+ D3 G  U! ~+ K    后来,我觉得S4A这个玩意挺好玩的,看了一下桌子上的Nucleo,决定来移植一下。经过大约3天的紧张工作,终于成功完成了移植。期间出了一个小小的问题耗费了大约一天的时间。也就是Nucleo和S4A通讯的时候,S4A总是崩溃,一直未响应。不知道是什么原因,期间一直在改动自己的代码。一天无果。第二天无意间换了FT232作为串口通讯的工具。竟然奇迹般的好了。事后发现,只要是Nucleo的串口,不出几分钟,S4A必然崩溃。不知道是Nucleo串口的原因还是S4A的原因。
, O9 G$ a2 b. p* [" H
+ Q# S4 [5 P5 W" g' G: [( U    在移植完之后,我简单的用S4A写了一个呼吸灯的程序,突然发现,用C很容易实现的东西,让我来拖拽的时候竟然不知道如何去做了。。。
; y: a+ R/ h! C+ ~( }) R3 N下面是程序截图:
' c! ], E9 d( {1 q. b. w5 H2 g9 b9 n
s4a.png 6 w. b, r* J# d& d/ C, C
最后,给大家上传一小段视频看一下(由于社区限制,只能将视频分成两个压缩包上传),感兴趣点个赞,不感兴趣路过好了。$ ^1 W; d( E8 V# k, }6 T4 [# D
- @9 E' |9 k2 n) @

2 l: w  O; P' b
---------------------------------------------------------------------------------------------------------------------------------------------------------------------9 H% X! M9 L  t! v2 ?" s
Nucleo334的软件包以上传到社区。欢迎大家下载试用。+ u" ^" o/ y  W
发帖的时候占用了3层楼。对这几层的规划:
. o0 ~4 _$ v+ {0 D  b* v+ D9 t) Y
  • 简单的介绍一下S4A软件如何使用。带领大家拖拽一个小程序。
  • 全面介绍一下如何将S4A在Arduino上的软件移植到STM的Nucleo板上。
  • 暂时还没想好能干点什么。) C, S! W2 R. [2 N
: o8 ^* C# X* @
9 j( n3 a/ H; `
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
$ K1 z; s8 s2 t& f1 q) v    软件包已经上传,名为S4Nu.rar(Scartch for Nucleo)欢迎大家提前下载使用。另外需要特别注意的是:虽然Nucleo自带了串口,但是在与S4A连接的时候不要使用这个串口。也不要使用USB连线将Nucleo与电脑相连。8 w  `: U+ A* H) o! t6 ]
    应该对Nucleo使用外部供电。并使用USB转串口工具,例如CP2102,FT232等连接电脑与Nucleo的串口。具体是什么原因暂时还未知。可能在接下来的几天内能够解决这个问题,也可能解决不掉。下面就要说说如何设置Nucleo的硬件部分:+ q9 z2 g% D" `
  • 将Nucleo复位按键(板子上面的那个黑色开关)下面的短路帽由U5V改成E5V。这样能切换到外部电源供电。
    # Q  G" y! w0 q1 ?
  • 将Nucleo背面的焊桥SB62和SB63短接。这样可以使PA2和PA3引脚连到Arduino接口的D0(Rx)和D1(Tx)。如果你懒得焊接,也可以使用CN3排针(STLINK)部分。CN3标记的RX接的是Nucleo的TX,而CN3的TX接的是Nucleo的RX。
    * B1 i5 @& _- f: w
  • 使用外部电源给Nucleo供电。外部电源5V接到Morpho左边排针的E5V,将外部电源GND接到Nucleo的GND。
  • 将你使用的串口工具的TX接D0或者CN3的TX串口工具的RX接D1或者CN3的RX串口工具的GND接Nucleo的GND,并将串口工具连接到电脑。
  • 打开S4A软件,S4A会自动搜索电脑上的串口,判断包格式。如果包正确,那么可以顺利连接。
  • 顺利连接之后可以看到S4A软件上显示的6路AD量和两路数字量输入。# Z; Z: t: J% B7 ~0 i+ d
    - _5 }* K% H0 y' ~& F1 `2 |
+ J$ m* b, z) `" G; i# D

7 M: z# P7 B1 `" P% A2 A( y7 i
  • 2015.6.9   更新2楼,介绍S4A如何使用。
  • 2015.6.10 更新3楼,介绍S4A Arduino源代码。
    2 c! [0 A  P, G( u: ^1 c

    . o" |7 W- O7 ~- q* S

, i4 O+ e( O: |: w$ c
8 k# Y' w/ S+ m; Q    因通讯的问题,给老外的技术支持发了一封邮件,几天后,收到了一个回复,大概意思说是他们的S4A只是为Arduino Uno和Duemienova定做的,并且在今后的升级中,会考虑兼容更多的板子。本以为这件事就这样算了。
3 B4 ]% l7 C4 k. k# b 1.png
7 T# q- T) `+ f    没想到,另一个人,猜测大概是S4A的开发人员,给回复了一封邮件。意思是他正在考虑让S4A在LPC的ARM处理器上工作。让我发送一下我的代码,说不定他可以检查到什么错误。好消息,给你吧。, d* E! e! Y$ E/ s
2.png
6 s- x, K3 H0 s3 B& H/ `! ?, _/ E    在发送完STM32的代码之后,静等了几天,昨晚收到了邮件回复:也没看出是什么软件的问题,大概是USB转串口的问题吧。: V8 N4 K) h* U5 Y4 ~& G" ]6 b1 y
wp_ss_20150623_0001.png * m) p; P; }8 ]6 {. {

  H) `& T4 |$ m# M1 T/ n' [
$ u3 L; H/ ?" w* V1 \

P1030138_20156818467.part1.rar

下载

9 MB, 下载次数: 248

P1030138_20156818467.part2.rar

下载

5.65 MB, 下载次数: 218

S4Nu.rar

下载

2.49 MB, 下载次数: 239

Nucleo334软件包

1 收藏 16 评论96 发布时间:2015-6-8 19:09

举报

96个回答
qianfan 回答时间:2015-6-8 19:12:46
本帖最后由 QianFan 于 2015-6-9 17:28 编辑 3 G7 ^# G* c' ?1 f# d
( b4 T2 j* v4 O3 a: T5 X7 E
Scartch的简单编程$ y8 O5 x1 L6 }6 i( V8 G
! L* n" B& f/ v' D6 H
    如果你代码下载完毕,串口连接完成,打开S4A之后,就可以看到6路AD模拟量和两个开关的数字量的值了。图中的COMx是你实际使用的串口。在我的电脑上,这个COM3是使用FT232转换出来的。还要注意图片中的旗帜的标志和那个红色的大圆点。旗帜代表运行我们使用S4A拖拽的程序,圆点代表停止。: c+ b8 s4 R/ t! p/ `' h$ s
scartch.png scartch.png   W  g- T. o1 J! J" X
; v* R' O  g" ]6 `8 k
    在S4A的左上角可以看到动作,控制,外观,等等控件。里面有各种各样的工具供我们使用。1 g6 v3 B9 e) {/ ^+ l9 n* D. s4 ~
  • 动作一栏含有数字引脚的输出,舵机控制,pwm输出等。是对硬件的实际控制。
  • 控制一栏中是常见的循环,if else分支语句,延时等函数。
  • 数字和逻辑运算里面含有常用的大于小于判断,加减乘除等语法。
  • 变量一栏中可以设置一个自己的变量,用于存储AD的采集值,pwm的输出值等等。更奇葩的是,还有链表这个东西。一直搞不清楚对小孩子而言,链表可以干什么。2 M% M+ A( H+ R0 ^: b# _
6 p# L9 U+ O! d" k, B* `9 Z4 {  @. H
    脚本这个位置就是我们写程序的地方。只要将程序按照逻辑结构放在这里就可以。一定要注意的是,开始的语句是一个“当旗帜被点击”的语句。这条语句类似于C语言中的main函数,程序开始执行的地方。下面就来简单的写一个闪灯的程序。! B- p: ^' [( }8 S/ x! v
scartch.png scartch.png
& |) I, R5 Y- p: g
( B; i5 N. ^# W
, n) `+ F% \6 z) u1 L* s    这就是我们平时在单片机中常写的Hello world程序。是不是很简单呢?如果想修改延时的时间怎么办?双击“等待1秒”中的1,然后填上你想要的时间并按回车。这个时间是小数的形式。可以是0.1 。* j+ C, E2 u! V' d5 c0 S

1 U( Y4 m; M4 {0 a0 F- F% g0 E    我们平时在写程序的时候,经常会设置一个变量,用于存储延时的时间。在S4A中,变量的设置也是支持的。在变量一栏中点击“新建一个变量”,之后填上变量的名字,就出现很多关于这个变量操作的控件。比如设置变量的值,将变量增加一个数值等等。可是,为什么没有减小变量的数值呢?其实只要将“将变量delayTime的值增加[]”中的空格处填写一个负数就可以了。比如-10 。可是小孩子如果不知道负数怎么办呢?
/ g/ C4 H! I3 B4 ]. R scartch.png 7 K- a. [4 o" Z1 a: ~: M
& w% k, C( z; G* k) |% E, E8 u
    在程序写完之后,点击右上角圆点旁边的旗帜图标就可以运行了。; S1 J3 z( L7 a5 H' l1 h( h3 }4 I; i
3 X. h% b+ d5 F& H* m
   不知道你家孩子会不会喜欢上!* Y( |: v9 a9 K5 w- x; G, N  v
6 L* X' F5 V# \# Q
- O) J1 d+ ^1 Y1 w. R, _

# @0 f4 R5 Q! o, ^2 t! C: g
. Z- r; c  t, Z% D- m" l! N& p' _- _8 L% E5 h
4 @% P% e* r( ?6 [4 b, P, I8 x
) d. p+ ^0 c' @; e4 M

* m$ j1 Z2 M6 {! j6 h3 x
qianfan 回答时间:2015-6-8 19:13:03
本帖最后由 QianFan 于 2015-6-10 14:30 编辑 4 j# U2 u! {3 J8 K

0 r/ y7 l; p7 n: c: o
S4A Arduino源代码解析
  A& y  W+ X. }% Y/ L" t

  Z2 n7 z8 _  K/ q- P( P4 u3 e/ @" f/ ?( O
准备工具:
* ?0 ], V) h3 ^. V4 p
  • Arduino IDE(如果没有,可以使用文本编辑工具代替。比如Notepad++或者记事本)。
  • S4A串口通讯协议。在附件中提供下载。
  • S4A Arduino通讯源代码。在附件中提供下载。
    4 p( @8 h: I. G' U/ T
3 Q$ y% x- ~# p$ V

* ]0 p6 x( f/ P/ W
Arduino的函数6 s8 X2 [0 h) Q+ q" ]
  1. int main( void )
    ' O$ W& k7 T% W3 J" ^; e$ D
  2. {% M; e( `" c! R
  3.         setup();- |9 _7 ^* x2 {
  4.         for (;;){
    5 r$ |( x5 v! B1 Y
  5.                 loop();2 @* J% v1 e% s6 J9 @6 J
  6.         }
    5 h0 f5 \3 O6 H0 F. U$ ]& T; D
  7.         return 0;
    ) O" e' H2 Y$ h. q
  8. }
复制代码
setup()和loop()是我们需要自己填充的。setup只会被调用一次,完成代码的一些初始化工作。loop是需要一直循环执行的。% X; l3 X8 k1 I# R7 N! I

: f/ l0 l0 c( {- ?/ ZArduino控制IO引脚的几个函数在arduino.h(SAM系列的在wiring_digital.h)中。5 `; W  x% I8 ?, h- D- B$ I
  • pinMode用于设置引脚的工作方式,可以是INPUT,OUTPUT。
  • digitalWrite是设置引脚的电平值。类似于STM32库文件中的GPIO_WriteBit。
  • digitalRead是读取引脚的电平值。类似于STM32库文件中的GPIO_ReadInputDataBit。
  • analogRead读取模拟引脚的电压值。因为Arduino是10位AD,所以这个函数的返回值在0-1023之间。
  • analogWrite并不是一个DA输出,而是pwm输出。在Arduino SAM中被改为了pwmWrite。
    + Y# ~2 p$ g4 w
  1. void pinMode(uint8_t, uint8_t);
    7 |* c( _: `$ a. q2 f
  2. void digitalWrite(uint8_t, uint8_t);
    4 x: F7 o' i1 b  A" ]
  3. int digitalRead(uint8_t);! _0 k1 ]7 I! _% ?' D
  4. int analogRead(uint8_t);% W+ K5 F& R: U8 h
  5. void analogWrite(uint8_t, int);
复制代码
* B3 X7 Z2 i& W4 q& G7 s

S4A的数据结构$ T) h' Q0 ^0 B8 |) u1 A- _
  1. typedef enum { # _0 [, k+ y- t! P
  2.   input, servomotor, pwm, digital } / c% U& q6 s/ Q) a0 R; w1 M, ~9 o
  3. pinType;& F3 }. `( c% `* A  Z0 \5 P

  4. 0 i9 M9 B( W& F# x9 N2 d, b9 ~
  5. typedef struct pin {
    ! g" \. w3 v/ m- T
  6.   pinType type;       //Type of pin/ K, U. j& }" K" `9 \" Q
  7.   int state;         //State of an output& R: d5 C- V( ~% t4 y% Y
  8.   //byte value;       //Value of an input. Not used by now. TODO8 V( B8 {" `0 \) p
  9. };   
    . h/ c6 l0 `  ~
复制代码
上面的代码在Arduino中确实能够编译。但是在C语言中确不能。不知道是不是C++中typedef的一个新特性,还是一个bug。我在移植的时候直接修改了这段:
6 ]( a+ x- D8 O/ F4 k
  1. typedef struct pin {; g' d, I! z9 O# }2 r: t4 n( A1 v
  2.   pinType type;       //Type of pin2 Z# S4 M6 b9 _6 n( `
  3.   int state;         //State of an output
    & {% a) j2 G( l( Z
  4.   //byte value;       //Value of an input. Not used by now. TODO
    . c- J) t! j( d" _& F6 y3 C8 K
  5. } pin ;- r$ R8 f- _* T: B
复制代码
struct pin是一个结构体,里面存储了引脚的信息,包括引脚的type和引脚的state。type是引脚的模式,可以是input,servomotors,pwm或者digital。state是引脚的值,有效取值从0到1023 。: X6 O, `& f9 d! i% D3 ^7 h
S4A规定:
( q  T' J. O# n" }/ r+ ]9 P
  • 如果一个引脚是input(用于输入)或者digital(用于输出),那么state取值只能0或者1023 。0表示低电平,1023表示高电平。
  • 如果一个引脚是servomotor(舵机接口)或者pwm,state的取值只能从0到255 。表示占空比。0表示占空比为0%,255表示占空比为100% 。5 a, U. O: _/ p
: M' _- C4 l9 H8 `1 H
S4A的Arduino源代码中定义了一个14个元素的数组,用来表示D0~D13的引脚的信息和状态:9 ?" a0 B9 d+ W
  1. pin arduinoPins[14]; //Array of struct holding 0-13 pins information
复制代码
S4A对每一个引脚的功能都加以区分:
' Z. a! F/ d1 I[原文]
% c# s& d, G6 @2 Q2 n4 `; o6 CComponents have to be connected in a particular way. S4A allows for 6 analog inputs (analog pins), 2 digital inputs (digital pins 2 and 3), 3 analog outputs (digital pins 5, 6 and 9), 3 digital outputs (pins 10, 11 and 13) and 4 special outputs to connect Parallax continuous rotation servomotors (digital pins 4, 7, 8 and 12).
  h$ ^; L* S' R  I! C9 N7 B
  • A0-A5,6路模拟量输入。引脚信息没有存放在arduinoPins数组中。
  • D0,D1是通讯串口的RX和TX。保留给串口使用。
  • D2,D3是两路数字开关量。可以用来接按键。pinType为input。
  • D4,D7,D8是舵机接口。pinType为servomotors。这三个舵机接口是通过延时函数来实现的。即使Nucleo板上发现这3个接口不是pwm接口也无所谓。
  • D5,D6,D9是pwm接口。pinType为pwm。使用逻辑分析仪测试,这三个pwm接口的周期都为2ms,频率为500Hz。
  • D10,D11,D12,D13是数字输出接口。pinType为digital。可以驱动led灯等设备。
    ! b2 @9 O2 V7 f; d) J9 C& m
" b3 h" ]$ H: P8 r& _* s

3 C( D# U1 S. k9 O
S4A的通信协议- l' X- e5 i  z6 \! Z/ c
根据S4A的通信协议(在附件中),每隔一段时间(20ms,在下文中会说明为什么是20ms),Arduino(或者Nucleo)应该依次将A0~A5的模拟量,D2,D3的电平值依次上传。共8组(一组数据由两个字节组成)数据。每一组数据都有相应的格式:
1 B1 |) T# c. }/ T& x1 J3 v" L$ k- f
7 6 5 4 32
: o9 k- S. s: ~, h+ \  P5 n
1 0
Byte1 1 N N N N R R R
Byte2 0 R R R R R R R
  • 每一个字节的最高位是一个标志位。Byte1的最高位必须为1,Byte2的最高位必须是0.这样就可以判断包是否正确。因为Byte1一定是大于127的,Byte2一定是小于127的。
  • N表示数据编号。Arduino上传至S4A:A0~A5模拟量的编号是0~5,D2编号是6,D3编号为7.
  • N表示数据编号。S4A下传至Arduino:D4~D13的编号为4~13 。
  • R表示需要上传的数据。由10位组成,可以表示0-1023的最大值。这也就是为什么STM32可以达到12位AD采集,却要设置成10位的原因了。' y1 n7 B) D0 }$ G& N' x, X
' f9 `# k+ j/ e$ @: P
举个例子:比如某一上传时刻,采集到了A0~A5的电压制为1023,D2为高电平,D3位低电平,那么应该上传:
$ {( l$ x( U4 TB1_0000_111 B0_1111111 //A0,1023
5 `3 J- t' s2 b, a3 ?B1_0001_111 B0_1111111 //A1,1023
8 D4 _" q7 |" X: v# u7 N8 AB1_0010_111 B0_1111111 //A2,1023
1 n/ _! ^7 ?$ o- Z: b% ]" _# J% M2 ^$ oB1_0011_111 B0_1111111 //A3,1023) _* i' u; E( ?
B1_0100_111 B0_1111111 //A4,1023
; z2 z1 E& C+ B; aB1_0101_111 B0_1111111 //A5,1023, I9 I  G* v) {/ t5 t
B1_0110_111 B0_1111111 //D2,HIGH
' l; W9 w% w6 q) G9 u8 D0 bB1_0111_000 B0_0000000 //D3,LOW8 I% O1 M# m/ Z7 |) j3 `

2 d7 `1 z3 F5 f. B; }: M1 {Arduino采集AD接口的信息的时候,一个AD接口采集了5次,取五次结果的中间值作为最后上传的结果:. _& M8 Z7 q* I" H
  1. for (byte p = 0; p < 5; p++)2 G6 @& Y. M. B7 ~6 K- b
  2.         readings[p] = analogRead(sensorIndex);* r& r! x; c) t9 h
  3.     insertionSort(readings, 5); //sort readings
    , t: a5 t' v7 _/ @; }! f3 k4 u9 d
  4.     sensorValues[sensorIndex] = readings[2]; //select median reading
复制代码
insertionSort是插入排序,将5次结果排序,那么五次结果中的第二个一定是中间值。5 u& }2 C, e2 ?( L0 F
索引
1 D% v  R( j, [: e( r
0 12 ) c1 ]# r$ U# g4 m
34 4 s8 \. \$ _7 E2 I
原始数据3 H% |  N' c% h# K' d# u) u: w
1023 1018 1020 1019 1021

2 N5 `! @- f* ~0 w! @% X* c9 M3 E
索引# h# Y, r- D$ x3 e& D& f
0 1 2 3 4
排序之后
: |2 a4 D: L% M" |6 z
1018 1019 1020 1021 1023

! O3 _0 R9 a6 y% n0 R, x/ N8 A$ |) `8 ]
在源代码中,将数据打包上传的代码:(Serial.write发送8位无符号整数)
2 F( o0 \. W6 [  `/ i1 P
  1. void ScratchBoardSensorReport(byte sensor, int value) //PicoBoard protocol, 2 bytes per sensor
    % y- P5 }  [+ D6 _. Q* w
  2. {
    - y. V4 m- h1 g8 E+ U$ |
  3.   Serial.write( B10000000
    & t1 `  j7 H; j2 q% m
  4.     | ((sensor & B1111)<<3)
    4 |! @/ V( z/ t; w. t: L8 ?0 ^* ]
  5.     | ((value>>7) & B111));
    # j& A' {4 w5 E0 A3 C( }
  6.   Serial.write( value & B1111111);7 }5 s- C8 F) h9 `$ H# K
  7. }
复制代码
而每隔大约75ms,S4A会将D4~D13的值传给Arduino。因为这个时间很短,为了保证数据的接受完整,在实际移植的时候,应该建立RingBuffer缓冲区,采用中断接收的方式。
5 V! o0 h1 F8 T" b+ J. B4 v- K" x3 p& ^* ^7 F# D9 c
[原文]Protocol                        9 f/ I- x  x: o$ T1 I- ?
S4A interacts with Arduino by sending the actuator states and receiving sensor states every 75 ms, therefore the pulse width needs to be greater than this time period. The data exchange follows the PicoBoard protocol and needs a specific program (firmware) to be installed in the board. Please refer to the Downloads section for further instructions on how to do so.
3 L4 z# s8 {  x2 g0 k1 c4 @- v5 Q
当Arduino接收到S4A传来的数据之后,会对数据解码,获取N编号和R的值:
7 h( o: X& b( `1 B
  1. pin = ((actuatorHighByte >> 3) & 0x0F);
    , @/ H2 ~. @- f  E
  2. newVal = ((actuatorHighByte & 0x07) << 7) | (actuatorLowByte & 0x7F);
复制代码
如果R值需要更新:. l) N/ N7 \; W- x6 v- ^4 K# r0 L
  1. if(arduinoPins[pin].state != newVal)1 S* W. t1 e; z
  2. {
    ) U6 x; t3 W5 H. x) \5 G: p, ^
  3.     arduinoPins[pin].state = newVal;9 z; M8 X. K1 _) X/ z3 K# P6 N" w
  4.     updateActuator(pin);4 R2 J" U# C2 d& D
  5. }
复制代码
而查阅updateActuator的代码,发现并没有更新舵机的代码(具体什么原因,会和上文提到的20ms一起解释)。7 G. ]* Y% y) w+ k* j  y7 O
  1. void updateActuator(byte pinNumber)& g0 v. A, V3 ?" O9 D& O
  2. {
    ! O+ R5 S1 K8 S# O
  3.   if (arduinoPins[pinNumber].type==digital) digitalWrite(pinNumber, arduinoPins[pinNumber].state);
    8 q' `! ]. X2 u9 c- A# a
  4.   else if (arduinoPins[pinNumber].type==pwm) analogWrite(pinNumber, arduinoPins[pinNumber].state);* J4 q. Z$ I( @# Y. l4 A8 L' \
  5. }
复制代码

) r7 j# i( ~7 K5 L
20ms?/ I/ r. E& x6 D1 x& q
loop函数是整个调用过程:
& p! Q! v5 z' z
  1. void loop()
    ! V+ h8 T; U3 `4 Y" e; {- U
  2. {
    5 \! g0 }4 u2 V4 s/ B
  3.   static unsigned long timerCheckUpdate = millis();7 s3 K& Z" P, \
  4. % ?+ y+ B9 ?3 H0 A6 A7 j, j5 M
  5.   if (millis()-timerCheckUpdate>=20)+ o$ ?. V. \$ V0 d* X
  6.   {
    ! A+ w; d. f2 H6 Y# o7 ?$ t& d
  7.     sendUpdateServomotors();
    ( [5 a( ?3 v5 {! Q& K. y1 N
  8.     sendSensorValues();" v+ L7 ~, g* l  ?9 r
  9.     timerCheckUpdate=millis();
    * K+ v: W$ }' t& Y3 O
  10.   }( K6 s  g- ?! e) S+ ?# F2 o( z8 i0 [" b4 K

  11. " x, Z% }- ~0 Y% K9 z
  12.   readSerialPort();
    * Q3 f( O  S  o! g9 A$ X$ q
  13. }
复制代码
由于C和C++的原因,上述代码在C中并不能成功编译。因此我修改为:
6 }) f0 h+ Y7 v
  1. void loop()
    9 \- |1 R* Q4 ^* C* x/ ?4 W6 f
  2. {
    8 F5 h) [/ @5 w4 k# I! S
  3.   static unsigned long timerCheckUpdate = 0;
    0 \, K( H- s, K% m! f  s$ H* L& K/ [
  4.   //...
    6 X. ]# Q- @* M5 Z0 ?7 W7 z" ?' f% `
  5. }
复制代码
   millis()是Arduino中用于获取自CPU启动以来经历的ms数。将timerCheckUpdate改为0,只不过第一次执行的时候if中的语句也能够执行罢了。在这20ms中,更新了舵机的数值,上传了A0~A5,D2,D3的状态。在最后更新了timerCheckUpdate时间戳,保证下一次执行是在20ms之后。如果这时候串口的接受缓冲区中存在数据,读出来,并解析。
. r& {$ c- b5 ]3 ?/ c    先科普一下舵机的知识:舵机的转动角度是0~180度,转动角度的大小是由pwm的占空比决定的。pwm的周期必须为20ms。pwm波形中高电平的时间大约在500us~2500us之间。500us代表0度,2500us代表180度。
& s' A+ o/ X- l" `/ Z: T
  1. void sendUpdateServomotors(), V+ H: l2 F, l) V" q6 k% q' R
  2. {  D4 |, I8 |0 _3 b  |8 Y, q
  3.   for (byte p = 0; p < 10; p++)
    ' Z$ a3 w6 G& `9 |( ~. X  W. f6 [/ C
  4.     if (arduinoPins[p].type == servomotor) servo(p, arduinoPins[p].state);- Z& h  N3 X, i
  5. }6 v9 x6 b, A6 N" L% ], H
  6. . ?2 ]+ l9 v- J% ]: L0 {* s  B9 ]
  7. void servo (byte pinNumber, byte angle)4 m; }. F# q' `# y1 D' v
  8. {
    # s& g( C! ]3 d1 R- y; u0 I' o
  9.   if (angle != 255)
    8 a" Y) ?# o3 d( B3 @- M
  10.     pulse(pinNumber, (angle * 10) + 600);- M2 L5 j* @% v- p$ U9 x
  11. }" j6 w5 w% K  U7 T3 w6 Z

  12. 0 _$ h+ v) b- x
  13. void pulse (byte pinNumber, unsigned int pulseWidth)/ g( _# c9 j" C! n& s( E; H0 m# S
  14. {
    ' c7 ]) S9 r/ x/ {3 a
  15.   digitalWrite(pinNumber, HIGH);- L% g1 X, y) P! e/ ~. q% i+ K* U
  16.   delayMicroseconds(pulseWidth);5 Z3 [* u) Q5 l6 `% A  g% R
  17.   digitalWrite(pinNumber, LOW);- h8 n' k+ ~. w1 G/ L( z. C$ Y
  18. }
复制代码
servo这个函数将S4A发送来的舵机的转动角度(0~180)转换成为实际的高电平时间。然后通过延时来产生一定时间的高电平。为了保证舵机能够正常运转。在移植的时候必须提供一个精度较高的delayMicroseconds函数。
0 y7 t5 C8 k$ L3 v5 e( J$ T
6 z" `9 S" {8 x% {8 o4 K6 l, G# {' W( O7 ?: t, _2 F  R

. l1 \+ L0 w: T; b- D
, J" C7 Y* u7 @" d) ~% CS4A的Arduino函数解析就这么多,希望大家都能够移植到自己的单片机中。- H: ^, x7 N- |8 g* ^
Have Fun!
; x- b8 d) t3 r
; k( W. I$ J7 u

s4a-protocol.pdf

下载

74.33 KB, 下载次数: 143

S4A软件串口协议

S4AFirmware16.rar

下载

2.61 KB, 下载次数: 114

S4A Arduino源代码

评分

参与人数 1ST金币 +30 收起 理由
zero99 + 30

查看全部评分

qianfan 回答时间:2015-6-8 19:13:21
占楼。。。
Paderboy 回答时间:2015-6-8 20:16:58
牛逼,Arduino上的图形化编程都让你搞过来
qianfan 回答时间:2015-6-8 20:22:33
Paderboy 发表于 2015-6-8 20:163 J3 D( b6 a' }
牛逼,Arduino上的图形化编程都让你搞过来

9 |& a: I# j5 h1 v  T- r: {7 g看到了通讯协议。之后的就很简单了。
qianfan 回答时间:2015-6-8 20:22:51
Paderboy 发表于 2015-6-8 20:16) o0 F! f4 `7 J6 \9 O
牛逼,Arduino上的图形化编程都让你搞过来

/ m5 Q8 j2 q7 P9 m不过视频录的不怎么样
风子 回答时间:2015-6-8 20:29:02
楼主大神啊,跟不上
qianfan 回答时间:2015-6-8 20:36:57
风子 发表于 2015-6-8 20:29
# V: T3 @8 T9 f0 I! _楼主大神啊,跟不上
$ o3 s# ]+ ]2 r& n
都是从小白开始的。现在会的也不多。。。只是觉得好玩
mark0668 回答时间:2015-6-8 21:06:51
哇。这东西好玩啊
jinyi7016 回答时间:2015-6-8 21:12:20
好强啊,希望有详细的教程 啊
creep 回答时间:2015-6-8 21:41:43
是不是要有Arduino才能玩啊
wamcncn 回答时间:2015-6-8 22:50:27
强啊,还不如个孩子,
党国特派员 回答时间:2015-6-9 06:59:49
谢谢分享。。。 null.png null.png null.png null.png null.png null.png null.png null.png null.png null.png
沐紫 回答时间:2015-6-9 08:44:37
good!
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版