争以Mac OS玩转nRF52840

识无涯

前面研究过一样种用于 如法炮制真
手写笔迹签名
的算法,  要求能够保原来笔迹平滑,并有笔锋的效果.

前言

在前面文章中已有介绍了[IoT](htt
p://baike.baidu.com/link?url=DJ6tLNPxTTUXnxbNVaQjRj3-nLZlILPlxDpdRDJ0Uhw__Jp-2WzbLroWzSph-mZUKcfdtiItYRCT8QvHyqh0C_),而BLE(低功耗蓝牙)作为当代智能机必备功能,是物联网的中心连接方式有。目前成千上万用如iBeacon,已经安排及我们活的广泛。

P.S. 如果你当地铁直达用一个支撑BLE的施用扫一扫,你晤面意识惊喜喔。

Bluetooth
SIG每当2016年新发生的
蓝牙 5.0 更是在低功耗的根底及存有了
更远、更快更安全之风味,关于蓝牙5.0的相关文章可参照这里。

以网上看了有些资料, 资料很多,
能够达到用于规范产品面临之效益的一个还不曾找到.

利其器

出于公司涉嫌,本人大概是在境内比较早以到 Nordic BT(BLE) 5.0
开发板
的开发者之一,到手瞬间倍感实物十分帅气:

Nordic nRF52840(pca10056)

只是出于自己长期工作吃Mac环境下,所以对大家常见应用Keil有接触不太适应,就折腾了Mac
OS下之支付调试环境,本文将享受这个折腾之历程。

好信息是,现在广大工具对Mac OS都曾经进展了协调的支持,如:

  • 调试器 J-link
  • 调试IDE Eclipse
  • 编译器 arm-eabi-arm-gcc
  • 自个人以的编辑器 Clion + Vim插件

自家见到最靠谱的相同篇稿子是这:Interpolation with Bezier
Curves

工具准备

  • ##### J-link for MacOSX

  • ##### Eclipse

  • ##### ARM gcc编译器

唯独就算按这首文章称的措施去落实手写笔迹, 表现的成效啊生之不理想.

安装(下载)大法

未雨绸缪好地方各种工具后,接下去我们需要未雨绸缪: VPN

P.S.
因为某个众所周知的案由,导致一些服务器上未失去要好缓慢,根据自家个人经历,在设置
Eclipse插件时,最好带达你的 VPN~~

而, 这首稿子还独自是事关到了笔迹平滑的题目, 没有提到到什么样解决笔锋的题材

一、安装arm-none-eabi-** 工具链

解压工具确保:

tar zxvf gcc-arm-none-eabi-4_9-2015q3-20150921-mac.tar.bz2

登工具确保目录:

sudo cp -r  gcc-arm-none-eabi-4_9-2015q3  /usr/local/  #复制工具到/usr/local中
sudo vim /etc/profile

当最终增加:

PATH=$PATH:/user/local/gcc-arm-none-eabi-4_9-2015q3/bin

增加后,退出,并运行:

. /etc/profile

运行成功后,便可通过terminal输入 arm-none-eabi-gcc
运行arm-gcc工具了。

经过自己一段时间的研究, 终于于齐洗手间的下(有没出吃duang了一晃之痛感,
哈哈~O(∩_∩)O),
想出来了平等种方法..先给大家来得两摆放在专业产品被之效果图:

二、安装Eclipse 插件

打开Eclipse Neon

点击Help->Eclipse MakertPlace,搜索GNU ARM

并安装GNU ARM 工具包:

装到位后,按照提示还启Eclipse。 重新打开后点击 Windows->Open
Perspective->other->packs

打开后点击刷新按钮,更新packs数据(此过程比较长…)

透过漫长的等候,刷新完成后,找到 Nordic
Semi->nRF_deviceFamilyPack

,选择新型版本进行设置,由叙可知,NRF52840_xxAA 已经在道支持中…

安装完成后,配置全局build工具及编译工具链路径:

眼前两摆放图片是于大哥大及测试的效应,后面两摆设凡当处理器及之所以鼠标写出来的效果.

仲、新建工程

下载nRF2840 SDK最新版本(由官网信息可知,最新版本已支持Bluetooth 5):

下载SDK后,解压至和睦的当地目录后,新建Eclipse工程导入:

当创建新工时,名字最好和Makefile 保持一致。
Makefile中之名:

工程名字:

选择对象芯片:

双重改编译命令为Make:

编译完成后,点解Debug便可以下载和调试程序:

以骨子里的安过程遭到深可能会见赶上各种不同的题材,我们得取在平等粒了解原理的心目才会迎刃而解那些奇葩的题目,单单只是于网上查学科,遇到真正问题经常我们累束手无策化解。
望君勿急躁,共勉~

图片 1图片 2图片 3图片 4

End

末段颁发一个好信息,硅谷 Season 4 已经开播啊~

 

本, 必须承认, 图片中显的机能效果的文,
我频繁写了森次…随便画几漫长线大概是如此:

图片 5

自将介绍的这种算法, 还好通过对某些参数的修改, 
模拟出毛笔, 钢笔, 签字笔等各种笔…真实书写效果
….

 

若是你还对贝塞尔曲线不了解,
我推荐查看这首文章:史书上无与伦比全的贝塞尔曲线(Bezier)全解,   所以,
在这里我会假设读者既对Bezier曲线已经比较了解.

正文主要谈解 如何通过就知晓所有笔迹点,
计算出控制点, 使用3不行bezier曲线拟合笔迹, 达到笔迹平滑的功效,
解决笔迹平滑的题材,.

而外本篇文章意外,
后面应该还会时有发生点儿首文章:

次篇:介绍自己开发的同样栽笔迹拟合算法.

老三首:主要介绍实现笔锋的效果.并提供最终的c++对之算法的落实之源代码和示范程序.

 Bezier曲线是经简单地指定端点和高中级的控制点(Control
Point)来描写出同样条油亮的曲线, 三不善贝塞尔曲线的效力是图表中如此:

图片 6

当红色的圆点代表本笔迹点时, 想必大家想只要之效益是下边图片被之蓝色线条,
而未是新民主主义革命线条吧:

图片 7

贝赛尔曲线拟合会通过前后两单端点,
但不见面经中间的控制点,所以,
我们由此贝塞尔曲线来拟合笔迹点的时段, 是要是:

于所有的笔迹点, 每相邻之同一针对笔迹点作为左右端点来绘制Bezier曲线,
所有我们要摸索有一部分满足某种规律的触发当这些端点中间的控制点.

下面请圈下图:

图片 8

图被, 点A, B, C为我们的原笔迹点, B’ 以及 B”呢咱计算出来的操纵点.

计量控制点的计是:

1) 设定一个0顶1之系数k,  在AB和BC上找到两碰, b’和c’, 使得距离比值,
Bb’ / AB = Bc’ / BC =
k  , 计算出些许个点
b’ 和 c’.
.(k的大小决定控制点的位置,最终决定笔迹的坦程度,
k越小, 笔迹越锐利; k越充分,则笔迹越平滑.)**

2) 然后每当b’ c’这条线段达到重复找到一个接触 t, 且线段的尺寸满足比例: b’t / tc’ = AB / BC,

3) 把b’ 和 c’, 沿着 点 t 到 点B的势头移动, 直到 t 和 B重合.
由b’移动继拿走 B’, 由 c’移动继的相距得到B”,
B’和B”就是咱若计算的在顶点B邻的一定量个操点.

实际上项目经过遭到,
使用下的规则进行绘图笔迹:

1) 当我们于手写原笔迹绘制的下, 得到第3个点(假设分别吗ABC)的时节,
可以测算出B点隔壁的少数独控制点., 由于是点A为从始点,, 所以直接把点A作为第一独控制点,
计算出来的B’作为次个控制点,  这样AAB’B
4单点,就可画出点A到点B的平滑贝塞尔曲线.(或者好一直把AB’B这3个点, 把B’作为控制点,
用二浅贝塞尔曲线来拟合, 也是可的哦~.)

2) 当得到第4只点(假设为D)的下, 我们由此BCD,
计算产生在点C附近的有限只控制点, C’和C”,
通过BB”C’C绘制出B到C的平滑曲线..

3) 当得到第i单点的时光, 进行第2只步骤………

4) 当得到最终一个点Z的下, 
直接把Z作为次只控制点(假设前一个碰为Y),  即,
使用YY’ZZ来绘制Bezier曲线.

为让阅读者能还好之敞亮, 用Python实现了这算法,
鼠标点击空白处可以多笔迹点, 选中笔迹点得动态拖动,
单击已出笔迹点实施删除:

力量图如下:

图片 9

Python代码我不怕不再说了, 直接提供出来:

  1 #!/usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 import numpy as np
  4 from scipy.special import comb, perm
  5 import matplotlib.pyplot as plt
  6 
  7 plt.rcParams['font.sans-serif'] = ['SimHei']
  8 # plt.rcParams['font.sans-serif'] = ['STXIHEI']
  9 plt.rcParams['axes.unicode_minus'] = False
 10 
 11 class Handwriting:
 12     def __init__(self, line):
 13         self.line = line
 14         self.index_02 = None    # 保存拖动的这个点的索引
 15         self.press = None       # 状态标识,1为按下,None为没按下
 16         self.pick = None        # 状态标识,1为选中点并按下,None为没选中
 17         self.motion = None      # 状态标识,1为进入拖动,None为不拖动
 18         self.xs = list()        # 保存点的x坐标
 19         self.ys = list()        # 保存点的y坐标
 20         self.cidpress = line.figure.canvas.mpl_connect('button_press_event', self.on_press)  # 鼠标按下事件
 21         self.cidrelease = line.figure.canvas.mpl_connect('button_release_event', self.on_release)  # 鼠标放开事件
 22         self.cidmotion = line.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)  # 鼠标拖动事件
 23         self.cidpick = line.figure.canvas.mpl_connect('pick_event', self.on_picker)  # 鼠标选中事件
 24 
 25         self.ctl_point_1 = None
 26 
 27     def on_press(self, event):  # 鼠标按下调用
 28         if event.inaxes != self.line.axes: return
 29         self.press = 1
 30 
 31     def on_motion(self, event):  # 鼠标拖动调用
 32         if event.inaxes != self.line.axes: return
 33         if self.press is None: return
 34         if self.pick is None: return
 35         if self.motion is None:  # 整个if获取鼠标选中的点是哪个点
 36             self.motion = 1
 37             x = self.xs
 38             xdata = event.xdata
 39             ydata = event.ydata
 40             index_01 = 0
 41             for i in x:
 42                 if abs(i - xdata) < 0.02:  # 0.02 为点的半径
 43                     if abs(self.ys[index_01] - ydata) < 0.02: break
 44                 index_01 = index_01 + 1
 45             self.index_02 = index_01
 46         if self.index_02 is None: return
 47         self.xs[self.index_02] = event.xdata  # 鼠标的坐标覆盖选中的点的坐标
 48         self.ys[self.index_02] = event.ydata
 49         self.draw_01()
 50 
 51     def on_release(self, event):  # 鼠标按下调用
 52         if event.inaxes != self.line.axes: return
 53         if self.pick is None:  # 如果不是选中点,那就添加点
 54             self.xs.append(event.xdata)
 55             self.ys.append(event.ydata)
 56         if self.pick == 1 and self.motion != 1:  # 如果是选中点,但不是拖动点,那就降阶
 57             x = self.xs
 58             xdata = event.xdata
 59             ydata = event.ydata
 60             index_01 = 0
 61             for i in x:
 62                 if abs(i - xdata) < 0.02:
 63                     if abs(self.ys[index_01] - ydata) < 0.02: break
 64                 index_01 = index_01 + 1
 65             self.xs.pop(index_01)
 66             self.ys.pop(index_01)
 67         self.draw_01()
 68         self.pick = None  # 所有状态恢复,鼠标按下到稀放为一个周期
 69         self.motion = None
 70         self.press = None
 71         self.index_02 = None
 72 
 73     def on_picker(self, event):  # 选中调用
 74         self.pick = 1
 75 
 76     def draw_01(self):  # 绘图
 77         self.line.clear()  # 不清除的话会保留原有的图
 78         self.line.set_title('Bezier曲线拟合手写笔迹')
 79         self.line.axis([0, 1, 0, 1])  # x和y范围0到1
 80         # self.bezier(self.xs, self.ys)  # Bezier曲线
 81         self.all_curve(self.xs, self.ys)
 82         self.line.scatter(self.xs, self.ys, color='b', s=20, marker="o", picker=5)  # 画点
 83         self.line.plot(self.xs, self.ys, color='black', lw=0.5)  # 画线
 84         self.line.figure.canvas.draw()  # 重构子图
 85 
 86     # def list_minus(self, a, b):
 87     #     list(map(lambda x, y: x - y, middle, begin))
 88 
 89     def controls(self, k, begin, middle, end):
 90         # if k > 0.5 or k <= 0:
 91         #     print('value k not invalid, return!')
 92         #     return
 93 
 94         diff1 = middle - begin
 95         diff2 = end - middle
 96 
 97         l1 = (diff1[0] ** 2 + diff1[1] ** 2) ** (1 / 2)
 98         l2 = (diff2[0] ** 2 + diff2[1] ** 2) ** (1 / 2)
 99 
100         first = middle - (k * diff1)
101         second = middle + (k * diff2)
102 
103         c = first + (second - first) * (l1 / (l2 + l1))
104 
105         # self.line.text(begin[0] - 0.2, begin[1] + 1.5, 'A', fontsize=12, verticalalignment="top",
106         #                horizontalalignment="left")
107         # self.line.text(middle[0] - 0.2, middle[1] + 1.5, 'B', fontsize=12, verticalalignment="top",
108         #                horizontalalignment="left")
109         # self.line.text(end[0] + 0.2, end[1] + 1.5, 'C', fontsize=12, verticalalignment="top",
110         #                horizontalalignment="left")
111         # xytext = [(first[0] + second[0]) / 2, min(first[1], second[1]) - 10]
112         #
113         arrow_props = dict(arrowstyle="<-", connectionstyle="arc3")
114         # self.line.annotate('', first, xytext=xytext, arrowprops=dict(arrowstyle="<-", connectionstyle="arc3,rad=-.1"))
115         # self.line.annotate('', c, xytext=xytext, arrowprops=arrow_props)
116         # self.line.annotate('', second, xytext=xytext, arrowprops=dict(arrowstyle="<-", connectionstyle="arc3,rad=.1"))
117 
118         # label = '从左到右3个点依次分别为b\', c\', t,\n' \
119         #         '满足条件 k = |b\'B| / |AB|, k = |c\'B| / |CB|\n' \
120         #         '然后把线段(b\'c\')按 t 到 B的路径移动,\n' \
121         #         '最后得到的两个端点就是我们要求的以B为顶点的控制点'
122         # self.line.text(xytext[0], xytext[1], label, verticalalignment="top", horizontalalignment="center")
123         self.line.plot([first[0], c[0], second[0]], [first[1], c[1], second[1]], linestyle='dashed', color='violet', marker='o', lw=0.3)
124 
125         first_control = first + middle - c
126         second_control = second + middle - c
127 
128         # self.line.text(first_control[0] - 0.2, first_control[1] + 1.5, '控制点B\'', fontsize=9, verticalalignment="top",
129         #                horizontalalignment="left")
130         # self.line.text(second_control[0] + 0.2, second_control[1] + 1.5, '控制点B\'\'', fontsize=9,
131         #                verticalalignment="top", horizontalalignment="left")
132         x_s = [first_control[0], second_control[0]]
133         y_s = [first_control[1], second_control[1]]
134 
135         # self.line.annotate('', xy=middle, xytext=c, arrowprops=dict(facecolor='b' headlength=10, headwidth=25, width=20))
136         arrow_props['facecolor'] = 'blue'
137         # arrow_props['headlength'] = 5
138         # arrow_props['headwidth'] = 10
139         # arrow_props['width'] = 5
140         # self.line.annotate('', xy=c, xytext=middle, arrowprops=arrow_props)
141         # self.line.annotate('', xy=first, xytext=first_control, arrowprops=arrow_props)
142         # self.line.annotate('', xy=second, xytext=second_control, arrowprops=arrow_props)
143         # self.line.plot([begin[0], middle[0], end[0]], [begin[1], middle[1], end[1]], lw=1.0, marker='o')
144         self.line.plot(x_s, y_s, marker='o', lw=1, color='r', linestyle='dashed')
145         # self.line.plot(x_s, y_s, lw=1.0)
146 
147         return first_control, second_control
148 
149     def all_curve(self, xs, ys):
150         self.ctl_point_1 = None
151         le = len(xs)
152         if le < 3: return
153 
154         begin = [xs[0], ys[0]]
155         middle = [xs[1], ys[1]]
156         end = [xs[2], ys[2]]
157         self.one_curve(begin, middle, end)
158 
159         for i in range(3, le):
160             begin = middle
161             middle = end
162             end = [xs[i], ys[i]]
163             self.one_curve(begin, middle, end)
164 
165         end = [xs[le - 1], ys[le - 1]]
166         x = [middle[0], self.ctl_point_1[0], end[0]]
167         y = [middle[1], self.ctl_point_1[1], end[1]]
168         self.bezier(x, y)
169 
170     def one_curve(self, begin, middle, end):
171         ctl_point1 = self.ctl_point_1
172 
173         begin = np.array(begin)
174         middle = np.array(middle)
175         end = np.array(end)
176 
177         ctl_point2, self.ctl_point_1 = self.controls(0.3, np.array(begin), np.array(middle), np.array(end))
178         if ctl_point1 is None: ctl_point1 = begin
179 
180         xs = [begin[0], ctl_point1[0], ctl_point2[0], middle[0]]
181         ys = [begin[1], ctl_point1[1], ctl_point2[1], middle[1]]
182         self.bezier(xs, ys)
183 
184         # xs = [middle[0], self.ctl_point_1[0], end[0], end[0]]
185         # ys = [middle[1], self.ctl_point_1[1], end[1], end[1]]
186         # self.bezier(xs, ys)
187 
188     def bezier(self, *args):  # Bezier曲线公式转换,获取x和y
189         t = np.linspace(0, 1)  # t 范围0到1
190         le = len(args[0]) - 1
191 
192         self.line.plot(args[0], args[1], marker='o', color='r', lw=0.8)
193         le_1 = 0
194         b_x, b_y = 0, 0
195         for x in args[0]:
196             b_x = b_x + x * (t ** le_1) * ((1 - t) ** le) * comb(len(args[0]) - 1, le_1)  # comb 组合,perm 排列
197             le = le - 1
198             le_1 = le_1 + 1
199 
200         le = len(args[0]) - 1
201         le_1 = 0
202         for y in args[1]:
203             b_y = b_y + y * (t ** le_1) * ((1 - t) ** le) * comb(len(args[0]) - 1, le_1)
204             le = le - 1
205             le_1 = le_1 + 1
206 
207         color = "yellowgreen"
208         if len(args) > 2 : color = args[2]
209         self.line.plot(b_x, b_y, color=color, linewidth='3')
210 
211 fig = plt.figure(2, figsize=(12, 6))
212 ax = fig.add_subplot(111)  # 一行一列第一个子图
213 ax.set_title('手写笔迹贝赛尔曲线, 计算控制点图解')
214 
215 handwriting = Handwriting(ax)
216 plt.xlabel('X')
217 plt.ylabel('Y')
218 
219 # begin = np.array([20, 6])
220 # middle = np.array([30, 40])
221 # end = np.array([35, 4])
222 # handwriting.one_curve(begin, middle, end)
223 # handwriting.controls(0.2, begin, middle, end)
224 plt.show()

大家也许认为这算法就较完善了, 下面我指出这种算法在实质上采用受到,
几单问题,  其中一些让人口完全不能够领:

1) 在骨子里交互过程中,
这种方法要3不好贝塞尔曲线来拟合, 用户输入完第3只点,才能够绘制第一漫漫曲线,
第4个点才能够绘制第2久曲线, 这种举报不立, 让经验十分差.

2) 每次都如算控制点, 非常麻烦, 并且还影响效率.

当生同样首文章被, 我会介绍自己实现之化解了这些老毛病的一律种植算法.

除此以外,
吐槽一下哟, 公司老板拖欠两个月工资了,  穷得叮当响,
每天吃8块钱之卵炒饭.真尼玛坑啊,我乘!!!!!!!!

大家要大家觉得就首文章对君发出扶持,
又肯打赏一些银两, 请拿起而的无绳电话机, 打开你的微信,
扫一扫下方二维码, 作为一个发斗志的程序员攻城狮,
我万分愿意接受大家的支助…哈哈哈!!!

图片 10