本学期,我报名了游泳 1,学习内容为蛙泳。通过十余周的学习,以及课下的多次练习,我成功掌握了蛙泳,并完成了各项课程任务。

蛙泳

本学期最大的收获就是学会了蛙泳。蛙泳是最简单的游泳动作,但是学习蛙泳的过程很不容易:

换气

要熟练掌握蛙泳,首先需要熟练掌握换气。换气前后,头要沉在水里,脸部几乎与水面平行。换气时,转动脖子让头浮出水面,下巴贴着水面,身体不动。快速吐出上一口气(可以发出“啪”的声音),然后吸入一口气,头回到水下。

需要注意的是:第一,换气时身体不要乱动(下水之后,换气时要保持双腿伸直夹紧),头不要抬得太高。如果身体过度倾斜,就容易失去平衡下沉。第二,换气速度要快。如果换气太慢,身体也会失衡下沉。换气太慢可能是因为对水产生了恐惧心理,不愿回到水下,需要多加练习克服恐惧。

蹬腿

掌握换气之后,就要练习蹬腿了。蹬腿前,腿伸直,脚面绷直。蹬腿动作可分为:第一步,双腿折叠,大腿垂直于上身,小腿贴近大腿,双脚勾起。第二步,大腿不动,小腿展开,脚面外翻,大小腿成“W”形。第三步,向外蹬腿,腿蹬直后并拢,脚面转为绷直。第四步,不动,等待身体滑行一段距离。简而言之就是“收翻蹬夹”。

需要注意的是:第一,蹬腿动作要规范,大腿不能过度折叠,小腿也不能过度展开,否则会影响发力。第二,蹬腿方向要正确,如果蹬腿方向太靠下,身体就会不由自主往上浮。第三,蹬腿速度不能过快,每蹬一次腿都要耐心等一下,以蹬一次腿换一口气为宜。

划手

最后需要学习的动作是划手。划手前,双手并拢,举到头顶上方最高处。第一步,双手翻掌,手背相对。第二步,胳膊伸直向两侧划手,划到肩宽之后,手臂缩回,双手在胸前合拢;此时应该抬头换气。第三步,双手合拢向前推出,推到头顶的位置;此时应该低头。第四步,手臂静止不动;此时应该蹬腿。

需要注意的是,划到肩宽以后就要收手,不要划到体侧。

换气、蹬腿、划手是蛙泳的三大动作,需要配合得当,多加练习,才能越游越快。

我们

我们先学习了蛙泳的换气动作,头泡在水里、手扒着岸边练习换气。之后学习蹬腿动作:先在垫上做动作,然后上半身趴在岸边、下半身浸在水里练习,最后手握浮板、腰系浮板下水练习,将换气与蹬腿结合起来。再然后学习划手动作:先在岸上练习,然后上半身浸在水里练习,最后撤掉手握的浮板,将三个动作结合起来下水练习。当动作熟练后,我们去掉腰上的浮板,独立完成游泳动作。

班里的大多数人只靠课上的练习就能轻松掌握游泳——但是我不行:才上了几周的课,就渐渐地跟不上了。于是我决定,每周都抽出一个半小时的时间去游泳馆练习蛙泳。本来是想拉上一个会游的,能方便指导我。但是人家会游的也不经常游,每次我去问都很难找到人陪我去游,于是我决定不求助别人,独自去练习了。

最初我很怕水,戴着浮板也不敢游,游几步就感觉自己不行了,换不上气了,要沉底了,淹死了。经过一段时间的练习,我终于可以戴着浮板游泳了。但是摘掉手上的浮板和摘掉背上的浮板之后,都出现了没游多远就沉底的现象。我去问老师,老师说是头抬太高了,还说换气太慢了,我试着改了改,但是并无成效。当时练习了两周都没有进展,非常气馁,晚上从游泳馆回来,感觉自己白练了那么久。但后来不知怎么的,就不会沉底了,逐渐能游 25 米、50 米、100 米、200 米了。这让我意识到了课下练习的重要性,持之以恒,就会有结果。

踩水

踩水是一项重要的救生技能。踩水时,双腿缓慢折叠,形成扎马步的姿势,然后双脚迅速向斜下方蹬直。踩水时需要注意:第一,动作要规范,蹬腿时一定要蹬直。第二,动作频率要适宜。如果害怕下沉而做动作太快,那么收腿时产生的阻力会增大,使蹬腿的效果减弱,反而会更快下沉。第三,蹬腿方向要正确,确保身体不会水平移动,如果身体向后移动说明蹬腿太向前,向前移动说明蹬腿太向后,需要及时调整。归根结底就是蹬腿时不要紧张,需要多多练习才能克服恐惧。

由于踩水动作只能在深水区练习,而每次课上只有半个小时的时间练习踩水,导致我的踩水动作并不熟练。由于害怕沉底,我蹬腿速度太快了,腿没有蹬直,而且身体会不由自主向后移动,只能漂浮 20 秒左右,之后就会沉底。在考深水证的那天,我牢记老师的叮嘱,经过短暂的练习,我终于掌握了规律节奏与身体平衡,最后成功通过了测试,拿到了深水证。这使我明白,直面挑战,才能克服困难。

出发

考试结束后,我们学习了出发动作。出发时,站在池边,双脚与肩同宽,脚趾勾住池沿,两个手掌朝向前方,一前一后贴在一起,后手大拇指勾住前手,胳膊伸直举过头顶,大臂要贴紧头后侧。然后蹲下,上半身尽量压低,手、手臂和上半身在一条直线上。最后,重心前倾,当快要失去平衡时,双腿蹬出,身体斜插入水中。

另一种做法是,双膝微蹲,上半身尽量压低,但是不要贴到大腿,通过弯曲上半身使手臂指向的方向斜向下。然后重心前倾,蹬腿入水。

需要注意以下几点:手掌动作要正确,蹲姿要规范,入水前一定要蹬腿,而且手臂角度要准确。太高会撞上水线,太低会插到池底,正确的做法是入水后留在水中层,手脚不动,从水线下方滑行过去。

准备活动和垫上运动

每节课下水前,老师都会带我们做准备活动。做好准备活动可以防止下水后抽筋。准备活动动作包括:头、扩胸、振臂、腰、体前屈、膝、正压腿、侧压腿、手腕脚踝。每个动作持续四个八拍。

老师还带我们做过一些垫上运动,锻炼我们的力量与柔韧性。但是具体怎么做的我忘了。

跑步过后,老师会带我们做拉伸动作。做好拉伸动作可以充分放松肌肉。拉伸动作包括:向前收腿提膝,双腿折叠,双手十指交叉抱住小腿;向前抬腿,小腿放平,双手吊住小腿;向后收腿,双腿折叠,同侧手拉住绷直的脚面。每条腿每个动作持续 10 秒。

更多

波浪式蛙泳可以加快蛙泳的速度。

老师教过我们蛙泳怎么转身,但是我当时忘了记录,现在已经忘了

除了蛙泳,还有很多泳姿,等待我们学习。

……

我在上游泳课的时候,观察到了一个现象:班上大部分人都只靠课上的时间练习,但是大部分男生都跟上了上课的进度,并且最后拿到了深水证;而只有寥寥几个女生拿到了深水证,甚至有些女生最后只能游 50 米,草草拿了个及格分。

这是为什么呢?我猜测主要是由于以下两个原因:

第一是女生比较怕水,在深水区不敢游。第二是女生力气比男生小,所以游泳容易下沉。这两个问题都会导致女生上课进度比男生慢,最终游不了 200 米;而解决方法只有一个——那就是在课下多练习。

另外,有人还有一个想法:

如果我考了证 以后看见有人落水我是救还是不救 救了万一我死了 不救万一ta死了我是不是会有心理负担 所以一开始就不要给自己选择的机会 在浅水区悠然自得就👌了

PWM

Arduino 可以直接输入模拟信号而无法直接输出模拟信号。但是,PWM 引脚可以通过调整占空比来输出不同幅值的电压,从而输出近似的模拟信号。(详见第 10 章)

(实验 10.1.2)使用 PWM 引脚输出近似的模拟信号,并使用模拟引脚读取,得到的电压变化如下图。其中平滑的曲线为理论上输出的电压,反复振荡的曲线是输入引脚读取的电压,也就是 PWM 引脚实际输出的电压。

使用模拟引脚读取 PWM 信号

但是,这个实验的结果很不精确,因为模拟引脚读取速度十分有限。使用示波器可以得到更为精确的结果:

使用示波器读取 PWM 信号

Timer

Arduino Uno 有三个定时器:Timer0、Timer1 和 Timer2。其中:

  • Timer0 用于 delay()millis()micros() 等函数,并控制着 5、6 号引脚的 PWM 输出;
  • Timer1 在基础实验中不使用,并控制着 9、10 号引脚的 PWM 输出;
  • Timer2 用于 tone() 函数,并控制着 3、11 号引脚的 PWM 输出。

产生电磁波

产生电磁波有两个条件:高频振荡信号和开放电路。后者可以通过接天线实现——当然,悬空的杜邦线也是可以的。下面着重说说前者:

本次实验中使用 Timer1 产生高频振荡信号。配置 Timer1 需要修改 TCCR1ATCCR1BOCR1A 等变量的值,较为麻烦。而 TimerOne 这个第三方库可以用来方便地配置 Timer1。使用以下代码即可在 9 号引脚处生成占空比为 50% 的 PWM 信号:

1
2
Timer1.initialize(1);
Timer1.pwm(9, 512, 1);

产生电报信号

tone()noTone() 函数可以产生指定频率的方波。将方波接入蜂鸣器,即可发声。

电磁波携带电报信号

将高频振荡信号与电报信号通过与门相叠加,再通过开放电路发射出去,即可实现发报功能。

使用示波器测量叠加后的波形,可以看到波形在微秒尺度上具有周期性:

最终发射的信号(比例尺 500ns)

但是,当比例尺缩小到毫秒尺度时,呈现的波形仍然具有周期性。这是为什么呢?我并没有找到原因。可能是因为波形振荡太频繁了,出现了显示错误。

最终发射的信号(比例尺 2ms)

延伸阅读

昨天(2月24日)晚上,我在写作业之余,去隔壁宿舍逛了逛。

刚一进门,原汁就向我求助。原来他在上学期的 C 语言课上学着写了一段生成全排列的代码,但是始终没有搞清楚代码的工作原理。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<stdio.h>

void f( int i ); // i 是正在执行的位数
int num[10]; // 存放每次排列
int a[10]; // 统计该数字有没有被用过

int n; // n 开成全局变量

int main()
{
scanf("%d", &n);
f( 1 );
return 0;
}


void f( int i )
{
if( i == n+1 ){
for( int cnt1=1; cnt1<=n; cnt1++ ){
printf("%d ", num[cnt1]);
}
printf("\n");
return;
}

for( int cnt=1; cnt<=n; cnt++ ){
if( a[cnt] == 1 ){ // 已经使用过这个数字
continue;
}
num[i] = cnt; // 将这个数字存入答案数组
a[cnt]++; // 记录已经使用过这个数字
f( i+1 ); // 进行下一步递归
a[cnt] = 0; // 回溯后将 a 数组归零
}
return;
}

输入数字 n,这个程序就能生成 1–n 的全排列。

原汁不明白,为什么如此简洁的 f 函数能够不重不落地生成全排列。我为他画了树状图,演示递归与回溯是如何进行的;可他还是不理解,于是自己亲手模拟了一遍。后来他又用 Dev-C++ 的调试功能监视了一些变量的变化,最后终于明白了。

这时我想到,我的电脑上装有 VSCode,里面的调试功能可能更高级一些,于是我用我的电脑调试了一遍:果不其然,VSCode 支持显示函数调用栈,清晰地向我们展示了递归与回溯的流程:(注:由于 gdb 不支持中文文件名,我将文件名换成了英文。)

调试界面

隔壁宿舍的高子也在用 VSCode,见状直呼牛逼。他也想用 gdb,但是当我帮他启动调试,向控制台中输入 4 的时候,却直接卡住了,没有任何反应。我按下 Ctrl+C 中止了调试,之前输入的内容立刻显示了出来。我上网查了许多方法,改了 VSCode 的配置,怎么都没有用。眼看时间已经过去了半个小时,问题还是没有解决,我想要放弃了。

最后,我对比了一下我和他屏幕上输出的调试信息,结果发现了端倪:

我输出的前两行调试信息如下:

1
2
=thread-group-added,id="i1"
GNU gdb (GDB) 11.2

再看高子的,如下:

1
2
=thread-group-added,id="i1"
GNU gdb (GDB) 7.6.1

好老喔,这么老的版本还支持吗?我去查了 VSCode 的官方教程,上面说的是“Get the latest version of Mingw-w64…”,看来最好还是用最新版吧。

高子正在用的是 MinGW,而 MinGW 早已停止了更新。我帮他下载了 mingw-w64(注:这是精简包,仅包含必要的功能。),解压出来,并修改了 PATH 环境变量。由于编译器路径写到了他的 VSCode 配置里,我又删掉了配置,这样 VSCode 才会在 PATH 中重新搜索。

至此,VSCode 调试环境的搭建终于成功了。有了 VSCode 强大的调试功能,高子的编程之路更进了一步。

今天,我的博客搭建完成了。

这个博客主要用来记录一些学习和生活方面的内容。除非另有声明,文章默认采用 CC BY-NC-SA 4.0 协议发布。

本博客使用 Hexo 搭建,托管在 GitHub Pages 上。优点是功能强大且完全免费,缺点是有一定的学习成本,而且有时网络会不稳定。

本博客的文章分为文章(post)和页面(page)两类:前者多为短篇,时效性较强,一般会开启评论;后者多为中长篇,时效性较弱。

大概就是这样。

0%