第一次把电容触摸屏接到主控板上,我盯着屏幕上那一串歪歪扭扭的点,第一反应是驱动写错了。查了半天时序、换了上拉电阻、把I2C速率从400kHz降到100kHz,那些点还是散着。后来才想明白,坐标本身没错,错的是我以为“读到一个坐标就等于画出一个点”。电容触摸屏给出的是一串离散的采样,画板要的是连续的笔迹,这两者中间隔着的不是一行代码,而是一整条从电荷变化到像素点亮的链路。
这次实验我把它定位成“触摸画板(1)”,先不追求多点、压感和笔刷效果,目标只有一个:手指在电容触摸屏上划过,画布上能出现一条连续、不跳、不断、笔尖跟手的线。听起来简单,但真做下来,坐标映射、中断读取、去抖、连线、刷屏这几块每一块都能卡人。下面我把这一版从原理到代码再到踩坑的完整过程拆开讲,适合刚接触电容触摸屏、想拿画板这类小项目练手的嵌入式朋友,也适合已经能读出坐标、但画出来的线一直不太对劲的人对照排查。
1. 电容屏上画一条线,中间要经过多少道手
很多人对触摸画板的第一印象是“读坐标、画点、完事”,实际链路比这个长得多。手指靠近屏体,电极上的电荷分布发生变化;触摸控制器按帧扫描整块屏,把每个感应节点的电容变化量转成数字量;控制器内部的算法做基线跟踪、阈值判定、质心计算,最终输出一组坐标和触摸状态;主控通过接口把坐标读回来;主控把触摸坐标映射到画布的像素坐标;绘制程序在帧缓冲里画点或者连线;最后刷屏,把帧缓冲推到显示面板上。任何一个环节掉链子,用户看到的就是跳点、断线或者笔迹滞后。
1.1 从手指到坐标:电荷变化只是起点
电容触摸屏的核心是电容。屏体内部有一层透明的导电电极,通常分成驱动电极和感应电极两组,交叉形成矩阵。手指是导体,靠近屏面时会改变电极附近的电场分布。自电容方案里,每个电极对地的电容会增大;互电容方案里,驱动电极和感应电极交叉点之间的互电容会减小。这个变化量非常小,一般在飞法到皮法量级,直接测量几乎不可能,所以控制器要发出激励信号,用电荷放大器把微弱的电容变化转成电压,再经过ADC变成数字量。
这里有个容易被忽略的点:控制器输出的不是“电容值”,而是相对于某个基线的变化量。基线会随着温度、湿度、屏体老化、电源波动缓慢漂移,所以控制器必须持续做基线跟踪。你如果发现设备放一会儿之后触摸变迟钝,或者刚上电时坐标正常、跑几分钟后开始飘,大概率不是你的映射代码写错了,而是基线跟踪的参数或者供电质量出了问题。我在实验初期遇到过一次,用不同电源供电时坐标偏移量完全不同,换了供电、加了去耦电容之后才稳定下来。
1.2 画板对触摸链路的三项硬指标
不是所有触摸参数都同等重要,画板这个场景真正敏感的是三项。第一是采样率,也就是控制器每秒输出多少次坐标。采样率低,手指快速划动时两个采样点之间隔得太远,画出来就是虚线。第二是坐标分辨率,它决定了笔迹的细腻程度,也决定了慢速画小字时会不会出现台阶。第三是坐标稳定性,手指静止不动时坐标的抖动幅度,抖动大,笔迹就会毛糙、发颤。
这三项指标互相牵制。提高采样率往往要缩短单帧扫描时间,信噪比会下降,稳定性变差;提高分辨率需要更精细的质心计算,处理器负担加重。实际选型时,我一般先确认采样率能不能覆盖最快的手写速度,再看静止抖动,最后才看分辨率。画板不是测绘工具,坐标分辨率够用就行,稳定性反而更影响观感。
1.3 这个实验适合谁,能练到什么
如果你刚学完I2C或者SPI,想找一个能看得到效果的练手项目,触摸画板是很好的选择,因为它把“总线通信、中断处理、数据处理、图形绘制、刷屏优化”串成了一条完整的链。如果你已经在做GUI,但触摸响应总是不跟手,这个实验也能帮你把问题定位到具体环节:是控制器采样慢,还是主控读取阻塞,还是刷屏占用了太多时间。
我建议动手之前先明确这一版的能力边界:单点触摸、固定笔宽、支持落笔、移动、抬笔,支持清屏和简单的撤销。多点缩放、压感笔宽、笔迹平滑的高级算法放到后面。边界清楚了,代码结构才不会一开始就写成一团。
2. 拆开触摸模组:传感器、控制器与主控之间的分工
一块能输出坐标的电容触摸模组,通常由屏体、柔性排线、触摸控制器三部分组成,有的还把控制器直接做在排线上。主控并不直接面对电极,它面对的是控制器暴露出来的寄存器和中断引脚。理解这三者的分工,能少走很多弯路。
2.1 自电容与互电容在画板场景下的取舍
自电容方案是逐个电极测量对地电容,结构简单、成本低、抗干扰相对好做,但它有个先天问题:多点触摸时无法区分真实手指和“鬼点”。两个手指同时按下,X方向和Y方向各有一组电极被影响,控制器会算出四个候选交点,分不清哪两个是真的。互电容方案扫描的是行列交叉点,每个交叉点独立测量,多点定位准确,还能做悬停检测和防水处理,代价是扫描通道多、成本高、算法复杂。
画板如果只做单指画线,自电容完全够用,而且坐标稳定性往往更好做。但如果你的产品后面要加双指缩放、手掌防误触,那就得从互电容方案开始设计,别等到后面再换屏。我在这个实验里用的是互电容模组,原因是手写时手掌边缘很容易搭到屏上,自电容方案下掌根一碰就会把笔迹拽走,互电容配合手掌抑制能明显改善。
2.2 触摸控制器内部到底在算什么
控制器不是简单地把ADC值除以一个系数就输出坐标。一帧扫描下来,它拿到的是整块屏的电容变化矩阵,接下来要做几件事:先用基线减去当前值得到差分;再用阈值判断哪些节点被触摸;然后对超过阈值的节点做质心计算,用加权平均的方式算出触摸中心,而不是简单取最大值点,这样坐标分辨率可以做到比电极间距更细;最后做去抖和跟踪,把连续几帧的坐标关联起来,分配给不同的触摸ID。
质心计算这一步很关键。假设电极间距是5毫米,只取最大值点,坐标分辨率就是5毫米一格;用质心加权,分辨率可以细化到1毫米甚至更细。但质心算法对噪声也敏感,边缘节点的权重不对称,手指靠近屏边时坐标容易往外偏。这就是为什么很多触摸屏在边缘画线会感觉“吸边”或者“够不到角”,属于算法层面的固有问题,靠应用层很难完全消除,只能通过校准补偿一部分。
2.3 接口与中断:为什么坐标不该轮询
控制器和主控之间常见的接口是I2C,速度快一点的有SPI。I2C的好处是引脚少、布线简单,400kHz速率下读一次坐标加状态一般也就几百微秒,对画板足够。SPI更适合高采样率或者大屏多节点的场景。
比接口更重要的是中断。控制器检测到触摸状态变化时,会通过INT引脚通知主控。正确做法是把INT配置成边沿触发,中断服务程序里只置一个标志位或者把坐标读进环形缓冲区,真正的映射和绘制放到主循环里做。不建议在中断里直接做I2C读加刷屏,I2C是阻塞操作,刷屏更慢,放在中断里会把整个系统的实时性拖垮。
我早期图省事用轮询,主循环里每10毫秒读一次坐标。结果画线时快一点就断,慢一点又觉得反应迟钝。后来改成中断触发加缓冲区,采样及时了,主循环也能专心刷屏,断线问题直接少了一大半。轮询不是不能用,但它把“什么时候有触摸”这个信息的获取主动权交给了主控的循环周期,天生就有一层延迟。
3. 实验台怎么搭:器件选型与接线里的隐藏条件
这一版实验的硬件不复杂:一块带控制器的电容触摸屏模组、一块主控板、一块用于显示的屏。如果触摸屏和显示屏是贴合在一起的一体模组,接线会更省事,坐标映射也更简单,因为两者的有效区域基本重合。如果是分离的,就要额外处理机械对齐和坐标系对应关系。
3.1 屏体、主控与显示部分的搭配逻辑
选型时我优先看三个参数:触摸控制器的接口类型、屏体的有效触摸区域尺寸、显示部分的分辨率和刷新方式。触摸区域和显示区域的比例决定了映射系数,两者尺寸接近时映射误差小;如果触摸区域明显大于显示区域,边缘一圈的触摸会被映射到显示区外,需要做裁剪。
显示部分我用的是并口或者SPI接口的小尺寸液晶,带帧缓冲。SPI屏刷全屏比较慢,假设分辨率是320×240、RGB565格式,一帧数据就是153600字节,按40MHz SPI理论带宽算,光传数据就要三十毫秒左右,实际加上命令开销更久。所以画板不能每画一个点就全屏刷新,必须做局部刷新或者脏矩形刷新。这一点在选屏阶段就要想清楚,否则后面笔迹跟手性很难做好。
3.2 硬件连接中容易忽略的电气细节
I2C的SDA和SCL需要上拉电阻,常见取值在2.2k到10k之间,具体看总线上挂了多少器件和走线长度。上拉太弱,上升沿变缓,高速下容易通信失败;上拉太强,功耗增加,某些控制器的灌电流能力有限。我一般先用4.7k,通信不稳再往下调。
触摸屏的柔性排线要尽量短,远离液晶的背光升压电路和电机的电源线。背光升压是开关电源,噪声频谱很宽,排线平行走一段就可能把噪声耦合进感应通道,表现为坐标周期性抖动或者触摸灵敏度下降。如果结构上避不开,中间加一层接地铜箔做屏蔽,铜箔单点接地。
电源去耦也别省。控制器的供电引脚旁边放一个0.1微法加一个1微法的电容,靠近引脚放置。我在一个实验板上遇到过触摸偶发失灵,查了两天才发现是控制器供电引脚的去耦电容离得太远,走线电感让电源在高频扫描瞬间塌陷。
3.3 上电顺序与复位时序
上电顺序不对,控制器可能起不来或者进入异常状态。通用做法是:先给控制器供电,等电源稳定,再把复位引脚拉低一段时间,然后释放,等待控制器内部初始化完成,最后才去读ID或者配置寄存器。复位低电平的持续时间和初始化等待时间要看具体控制器的数据手册,常见是几毫秒到几十毫秒,保守一点等一百毫秒也不亏。
有个细节值得注意:如果主控和触摸控制器共用电源,主控复位期间电源可能有波动,触摸控制器可能被意外复位。稳妥的做法是在主控启动后主动对触摸控制器做一次硬复位,再走初始化流程,别假设它一定处于干净状态。我在调试时就吃过这个亏,热重启之后触摸偶尔不响应,加了主动复位之后问题消失。
4. 最小闭环:把第一个触摸点画到画布上
硬件通了之后,先别急着写画板,第一步是把“读到正确坐标”这件事做扎实。我的习惯是先写一个坐标打印程序,手指点在四个角,看串口输出的原始坐标范围和方向是否正确。这一步能提前发现X/Y交换、镜像、坐标范围异常等问题,比在画板里调试直观得多。
4.1 控制器初始化与ID自检
初始化流程一般是:读芯片ID确认通信正常,写配置寄存器设置工作模式、扫描周期、中断触发方式,清一次中断状态,然后使能触摸检测。读ID这一步别跳过,它是区分“总线不通”和“控制器没启动”的最快手段。ID读出来是0或者0xFF,基本就是接线或者上拉的问题;ID正确但坐标不动,再往配置和中断方向查。
static int tp_init(void) { uint8_t id = 0; if (i2c_read_reg(TP_ADDR, REG_CHIP_ID, &id, 1) != 0) return -1; if (id != TP_CHIP_ID_EXPECT) return -2; i2c_write_reg(TP_ADDR, REG_CTRL, CTRL_SCAN_100HZ); i2c_write_reg(TP_ADDR, REG_INT_MODE, INT_EDGE_FALLING); i2c_write_reg(TP_ADDR, REG_THRESHOLD, 0x28); i2c_write_reg(TP_ADDR, REG_ENABLE, 0x01); delay_ms(50); return 0; }上面的寄存器名和数值是示意,实际要按你手上控制器的数据手册来填。阈值这一项建议先用默认值跑通,再根据实际手感微调。阈值设得太低,手指还没碰到屏就触发;设得太高,轻触识别不到,画细线时容易丢笔。
4.2 一次完整的坐标读取流程
中断来了之后,读取流程一般是先读状态寄存器,确认有几组坐标、是否处于按下状态,再读对应的坐标寄存器,最后写清除中断寄存器。有的控制器读坐标时会自动清中断,有的必须手动清,漏清会导致中断只来一次,后面再也不触发,表现就是“只能画一个点”。
void tp_isr(void) { tp_event_t ev; uint8_t st = 0; i2c_read_reg(TP_ADDR, REG_STATUS, &st, 1); if (st & STATUS_TOUCH) { uint8_t buf[4]; i2c_read_reg(TP_ADDR, REG_X_H, buf, 4); ev.x = ((uint16_t)buf[0] << 8) | buf[1]; ev.y = ((uint16_t)buf[2] << 8) | buf[3]; ev.pressed = 1; } else { ev.pressed = 0; } i2c_write_reg(TP_ADDR, REG_INT_CLEAR, 0x01); ringbuf_push(&tp_ring, &ev); }中断服务里只做读取和入队,映射和绘制留给主循环。这样即使主循环正在刷屏,触摸事件也不会丢,最多是延迟几毫秒处理。
4.3 从触摸坐标到屏幕像素的映射
映射看起来就是两个比例公式,实际有几个坑。控制器的原始坐标范围可能不是屏幕分辨率,比如0到4095;X轴和Y轴可能是反的;有的屏装反了180度,需要同时翻转两个轴。最稳妥的办法是先用打印程序记录四个角的原始坐标,再写映射。
static void map_to_pixel(uint16_t raw_x, uint16_t raw_y, int16_t *px, int16_t *py) { int32_t x = ((int32_t)raw_x - RAW_X_MIN) * (LCD_W - 1) / (RAW_X_MAX - RAW_X_MIN); int32_t y = ((int32_t)raw_y - RAW_Y_MIN) * (LCD_H - 1) / (RAW_Y_MAX - RAW_Y_MIN); if (x < 0) x = 0; if (x > LCD_W - 1) x = LCD_W - 1; if (y < 0) y = 0; if (y > LCD_H - 1) y = LCD_H - 1; *px = (int16_t)x; *py = (int16_t)y; }裁剪不能省。原始坐标在边缘会有溢出,映射之后变成负数或者超出屏幕,直接画点会踩到帧缓冲越界,轻则花屏,重则死机。这个坑我在第一次写的时候踩过,手指划到屏边,画面直接乱掉,查了半天以为是刷屏驱动的问题。
4.4 描点与连线:Bresenham的必要性
采样点是离散的,如果每个采样点只画一个像素,快速划动时两点之间会隔开几十个像素,画出来是虚线。必须把相邻两个采样点用直线连起来。这里不要用浮点斜率和逐点计算,整数版的Bresenham算法足够快,也不会有舍入误差累积。
static void draw_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) { int16_t dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; int16_t dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; int16_t err = dx + dy; for (;;) { lcd_draw_pixel(x0, y0, color); if (x0 == x1 && y0 == y1) break; int16_t e2 = err << 1; if (e2 >= dy) { err += dy; x0 += sx; } if (e2 <= dx) { err += dx; y0 += sy; } } }相邻采样点之间要不要连线,取决于采样间隔。采样率100Hz、手指移动速度每秒200毫米、屏宽100毫米对应320像素,算下来每帧移动约6.4像素,这个间隔必须连线,否则笔迹是断的。如果采样率提高到200Hz,间隔减半,但画的点变密,绘制开销也上去,要结合主控性能权衡。
5. 第一版跑起来之后:跳点、断线与拖影的现场排查
能画出线只是开始,真正花时间的是把线画稳。我按照现象把问题分成三类:点乱跳、线断开、笔迹拖影或者滞后。这三类的根因完全不同,混在一起调很容易越调越乱。
5.1 跳点的三种来源与区分方法
跳点是指手指匀速移动时,笔迹上突然冒出一个偏离主轨迹的点。常见来源有三个。第一种是边缘效应,手指靠近屏边或者角落时,质心计算不对称,坐标往外偏,表现为笔迹在边界附近被“吸”出去。第二种是手掌或者第二根手指误触,控制器把质心算到了两个接触面的中间。第三种是电源噪声或者基线漂移,坐标整体周期性抖动。
区分方法很简单:手指静止放在屏幕中央,观察坐标的方差,方差大说明是噪声或者基线问题;手指沿边缘缓慢画一圈,看偏移是否只在边缘出现,是的话就是边缘效应;手掌悬在屏上方靠近,看坐标是否被拉走,是的话就是误触或者悬停灵敏度太高。这三种情况的处理方式不一样,边缘效应靠校准和应用层限幅,误触靠调整阈值和手掌抑制参数,噪声靠硬件滤波和供电改善。
5.2 断线不是滤波能解决的
很多人一看到断线就去加滤波,结果线更断了。断线的本质是采样点之间缺失,滤波只会让已有的点更平滑,补不出丢失的点。断线的常见原因有三个:采样率不够、主循环阻塞导致事件处理延迟、中断丢失。
先测采样率。在中断里翻转一个GPIO,用示波器看频率,或者用定时器计数,看每秒实际进入中断多少次。如果远低于配置值,说明主循环里有阻塞操作,比如全屏刷新的时间太长,把中断响应拖慢了。解决方向是局部刷新、DMA传输、把耗时的绘制拆到空闲时间做。
如果采样率正常但线还是断,检查环形缓冲区是不是溢出了。刷屏期间如果缓冲区太小,事件会被覆盖,表现就是随机丢点。把缓冲区加大到能存几十个事件,通常就能缓解。还有一个隐蔽的原因是I2C读取失败没有重试,偶发的总线冲突导致某次坐标读取返回错误值,直接丢弃就形成了一个缺口。
5.3 抬笔判定的边界情况
抬笔判定看起来简单,控制器状态位一变就结束笔画,实际有几个边界。第一是快速抬笔,手指离开得很快,最后一个采样点可能没被读到,笔迹末尾会短一截。第二是轻触,手指只是轻轻碰一下,压力不够,控制器可能只报告一两帧就消失,画出来是一个点,也可能完全没反应。第三是停留,手指按住不动,控制器仍然持续上报坐标,如果不做处理,会不断在同一个位置重复画点,浪费绘制时间。
我一般用状态位加超时双重判定:状态位显示抬起就立即结束;如果状态位一直显示按下但坐标超过一定时间没有变化,也视为笔画结束,避免手指被识别为长时间停留时一直占用绘制资源。快速抬笔丢点的问题,可以在收到抬起事件时用最后一个有效坐标补一个终点,视觉上会好很多。
6. 让笔迹像笔迹:滤波、平滑与插值的取舍
硬件和读取流程稳定之后,剩下的就是画质问题。原始坐标一定带噪声,直接用会画出毛刺。滤波是必须的,但滤波会引入延迟,延迟大了就不跟手。这块没有标准答案,只能根据手感调。
6.1 滑动平均与中值滤波的组合用法
滑动平均是把最近N个坐标取平均,实现简单,对高斯噪声效果好,缺点是会模糊快速移动时的拐角。中值滤波是取窗口内的中位数,对脉冲型噪声特别有效,比如偶发的跳点,而且不会像平均那样把边缘拉平。我的做法是先用窗口为3或者5的中值滤波去掉孤立跳点,再送进滑动平均做轻度平滑。
static int16_t median3(int16_t a, int16_t b, int16_t c) { if ((a <= b && b <= c) || (c <= b && b <= a)) return b; if ((b <= a && a <= c) || (c <= a && a <= b)) return a; return c; }窗口不要开太大。窗口为5时,延迟大约是2到3帧,100Hz采样下就是二三十毫秒,还能接受;窗口开到9以上,画快线时明显感觉笔尖在后面追。中值滤波的窗口最好是奇数,3是最常用的起点。
6.2 一阶低通滤波器的参数直觉
一阶低通的形式是y[n] = α * x[n] + (1 - α) * y[n-1],α越大越跟随原始值,α越小越平滑但延迟越大。α取1等于不滤波,取0等于完全不动。画板场景我一般从0.4到0.6开始试,慢速画细节时希望α小一点,快速划线时希望α大一点,可以做成动态的:根据移动速度调整α,速度越快α越大,减少延迟;速度越慢α越小,增加平滑。
这个动态调整的思路不复杂,但要注意切换时不要突变,否则笔迹会有顿挫感。可以用速度做线性插值,在两个α值之间平滑过渡。实测下来,动态α对跟手性和平滑度的平衡比固定α好不少。
6.3 插值补点与曲线拟合的边界
插值是在两个采样点之间补出中间点,让笔迹更连续。线性插值最简单,沿着两点连线均匀取点,本质上和Bresenham画线效果类似,适合采样间隔不大的情况。二次或者三次曲线拟合能让拐角更圆润,但容易过冲,手指画直角时会被拟合成圆弧,反而失真。
我的建议是先用连线加轻度滤波跑一段时间,确认采样率足够、没有丢点,再考虑要不要上曲线拟合。很多所谓的“笔迹不够顺滑”,根因其实是采样率不够或者有丢点,插值只是在掩盖问题。真正需要曲线拟合的场景是采样率固定但用户手速很快,这时候补点和拟合才有意义。
7. 校准:让笔尖落在该落的地方
即使映射公式写得没问题,实际画出来的线也可能和手指位置对不上,尤其是屏幕边缘。原因包括屏体制造公差、触摸层和显示层贴合偏移、控制器内部的非线性。校准就是采集一组已知位置的原始坐标,拟合出一个补偿关系。
7.1 为什么线性映射不够用
线性映射假设原始坐标和像素坐标是严格比例关系,但实际屏体的边缘电场不均匀,质心算法在边缘的偏差不是线性的。表现就是屏幕中央对得准,四个角偏几个像素,越靠边偏得越多。对于画板这种需要精确落笔的场景,几个像素的偏差已经能感觉到。
校准的本质是求解一个从原始坐标到像素坐标的变换。最简单的仿射变换包含六个参数:x方向的比例和偏移、y方向的比例和偏移、以及两个轴的交叉项。交叉项用来补偿屏体旋转或者贴合歪斜。采集三个不共线的点就能解出六个参数,采集四个点或者更多点则可以用最小二乘降低单点误差的影响。
7.2 四点校准的实现与验证
四点校准的做法是在屏幕上显示四个靶点,让用户依次点击,记录每个靶点的原始坐标和对应的目标像素坐标,然后用最小二乘求仿射变换的系数。
| 步骤 | 操作 | 注意事项 |
|---|---|---|
| 1 | 显示四个角靶点 | 靶点离边缘留10到20像素,避开边缘非线性区 |
| 2 | 采集原始坐标 | 每个点连续采多帧取平均,减少噪声影响 |
| 3 | 求解仿射系数 | 用最小二乘,四个点可以容忍单点误差 |
| 4 | 写入非易失存储 | 存之前做一次范围检查,防止写入异常值 |
| 5 | 验证 | 画十字线和边框,检查四角和中心是否对齐 |
求解出来的系数在运行时直接参与映射,计算量很小。要注意的是,校准数据要和屏体绑定,换屏之后必须重新校准。如果产品是小批量,可以在产线做一次校准写入;如果是开发阶段,建议留一个校准入口,方便反复调。
验证的时候不要只看四个角,中间和边中点也要看。我遇到过一次四角都对得很准,但边中点偏了三个像素,原因是四个靶点采集时手指按的压力不一致,质心偏移量不同。后来改成每个点采集十帧取平均,并且提示用户用正常力度点击,偏差才降下来。
8. 这一版能做什么、不能做什么
到目前为止,这一版画板能稳定做到单指画线、清屏、简单撤销,笔迹连续性和跟手性在常规手速下可以接受。它不能做多点缩放,没有压感,笔宽固定,快速划动时边缘仍然会有轻微偏移,屏幕角落的精度依赖校准质量。这些限制我在开始就接受了,因为这一版的目标是打通链路,而不是做一个成品绘图工具。
如果后面要继续往下做,我会先解决快速划动的断线,方法是把刷屏改成脏矩形加DMA,把主循环从刷屏里解放出来,再考虑多点触摸的ID跟踪和压感笔宽。手掌抑制也值得单独调一轮,尤其是画画时手腕搭在屏上的场景,阈值和滤波参数要重新标定。
最后分享一个我做这类实验一直坚持的习惯:每改一个参数,只改一个,改完立刻用固定的手速画三条线做对比,一条慢线、一条快线、一条斜线。三条线的表现能覆盖大部分问题,比随手画几笔靠谱得多。参数记录在本子上,写清楚改之前是什么、改之后是什么、现象有什么变化,过几天回头查的时候能省很多时间。