基于STEP Pico实现一个水平仪
2023寒假一起练平台,基于Step Pico实现一个水平仪项目。
标签
Arduino
树莓派RP2040
2023寒假在家练
STEP Pico
Hessian
更新2023-03-29
358

基于STEP Pico实现一个水平仪

项目背景

这是一个2023寒假一起练平台(1)- 基于STEP Pico的嵌入式系统学习平台项目。

项目提供了一块Step Pico的开发板和树莓派Pico的扩展板,可以使用C/C++或者Micropython进行开发,项目还提供了配套的Micropython课程。

看到这个项目的任务列表的时候我一下就选中了“项目5 - 制作一个水平仪”这个任务,因为之前还没有接触过姿态传感器,正好借这个项目的机会学习一下。

任务的具体要求是:利用板上的姿态传感器,在OLED屏上通过小球滚动的方式显示板子的倾斜度,板子水平的时候小球处于OLED显示器的中心位置

实现方式:通过I2C总线访问板上的姿态传感器MMA7660的信息(可以以查询或中断的方式),经过数据处理以后判断板子的运动状态,在OLED屏幕上绘制一个能够滚动的小球,根据得到的数据调整小球的位置。

 

开发前的准备工作

作为一个多年使用脚本语言进行开发的老程序员,虽然是刚开始接触嵌入式开发,STEP Pico也提供了更方便开发的Micropython的教学视频,但是我依然选择了C/C++进行项目开发,主要原因还是刚开始入门,之前也学习了一点Arduino,开发起来还是更加顺手一点。

 

那么开始之前首先是配置环境。工欲善其事必先利其器,一个新手想要快速的学习一种编程语言、框架,我觉得趁手的开发工具都是必不可少的,虽然想用Arduino开发,但是ArduinoIDE实在是拉胯。不管是从开发的便利性、代码文件的管理能力还是编译速度都感觉跟不上时代。作为多年的JetBrains用户,已经很习惯了他们家的IDE,之前看到可以用platform.io结合Clion开发Arduino程序,那么JebBrains Clion就是我的不二选择了(才不是因为买全家桶舍不得浪费)。

 

首先安装Clion和platform.io,并在Clion内安装上platform.io的plugin我们就可以开始进行开发了。

先用platform.io创建一个项目,Board选Raspberry Pi Pico,Framework我们选Arduino。然后用clion打开这个项目。在项目里我们会用到U8g2、Accelerometer_MMA7660和Adafruit NeoPixel几个库。通过platform.io的Libraries界面可以找到并进行安装。

FisVs8HcXgZMhiuMETI-B1ba2hfV

设计思路

根据任务要求是读取姿态传感器MMA7660的信息在OLED屏上显示一个滚动小球,板子水平时小球要处于屏幕中央的位置。通过Accelerometer_MMA7660库的getAcceleration方法我们可以可以得到板子在X、Y、Z 三个轴上的偏移量,范围是-1到1的浮点数,我们只要以屏幕中心为坐标原点,根据XY的偏移量即可计算出小球在屏幕上的位置,用u8g2库函数进行绘制就完成了项目要求。

程序流程图

FhJM9PsXG8Ny0OAUcnfVUvPD9pHM

顶视图的主要代码

/**
 * 俯瞰顶视图
 */
void topView()
{
    Point3 ap = getFilteredPoint();
    Point ballPos{64 + 64 * ap.x, 32 + 32 * ap.y};

    u8g2.drawCircle(64, 32, 10);
    u8g2.drawDisc(ballPos.x, ballPos.y, 3);

    if (ballPos.x < 32) {
        ballPos.x = 32;
    }
    if (ballPos.x > 96) {
        ballPos.x = 96;
    }

    for (int i = 0; i < RGB_RING_NUM; ++i) {
        int d = min(distance(&ballPos, &led_positions[i]), 64);
        if (d > 32-5) {
            strip.setPixelColor(i, 0);
        } else {
            strip.setPixelColor(i, Adafruit_NeoPixel::Color(0, 255 / 32 * (64-d), 0));
        }
    }

    strip.show();
}

 

完成项目要求是比较简单,但是作为一个练习项目,我还是希望多用上一些板载的器件以学习到更多的器件用法。那么加入一点灯光控制似乎也挺有趣,ws2812之前也没有用过,这里我又加了一点小功能,根据小球所处的方向,点亮对应方向上的ws2128灯珠,并根据距离调整灯珠的亮度。

 

这里实现起来会稍微复杂一点,首先我给屏幕周围的12颗灯珠都在坐标系里虚拟了一个坐标,然后通过计算得到小球坐标与灯的坐标的距离,根据距离的远近控制灯珠亮度的强弱就可以使距离小球较近的灯珠变量。

 

整个项目做完还是感觉比较简单,而且我不确定任务重所指的小球滚动是以什么样的模式进行,于是我又增加了一个展示模式,并学习了一下通过中断响应按键事件的方法。

 

程序默认为展示顶视图的水平仪,按下K2可切换为前视图的水平仪,小球仅在水平方向上滚动仅可用于检测一个轴上的倾斜变化。

 

为了增加趣味性,我还增加了一个可以根据倾斜度不断滚动的小球,倾斜度越大,其滚动速度也越快。

 

在开发过程中为了方便调试,我给按键K1也增加了一个可以开关调试信息显示的功能,可以随时在屏幕上打印出MMA7660的数据信息,以便调试。

 

前视图的主要代码

/**
 * 前视图
 */

double ballX = center.x;

void frontView()
{
    Point3 ap = getFilteredPoint();

    if (ap.z > 0.5) {
        u8g2.drawUTF8(30, 34, "请竖起屏幕");
        return;
    }

    if (debug_enabled) {
        char buf[64];
        sprintf(buf, "%.3f %.3f %.3f", ap.x, ap.y, ap.z);
        u8g2.drawStr(0, 30, buf);
    }

    ballX += (-ap.x) * 8;

    if (ballX > DISPLAY_WIDTH) {
        ballX = DISPLAY_WIDTH;
    }
    if (ballX < 0) {
        ballX = 0;
    }

    u8g2.drawHLine(0, DISPLAY_HEIGHT - 5, DISPLAY_WIDTH);
    u8g2.drawCircle(ballX, DISPLAY_HEIGHT - 11, 5);

    u8g2.drawHLine(0, 30, DISPLAY_WIDTH);
    u8g2.drawVLine(center.x, 25, 10);

    int x = (-ap.x) * center.x + center.x;
    u8g2.drawCircle(x, 25, 5);

    if (abs(ap.x) < 0.1) {
        strip.fill(Adafruit_NeoPixel::Color(0, 10, 0), 0, RGB_RING_NUM);
    }


    strip.show();
}

 

主要难点

  • 找到的MMA7660库不能指定I2C PIN的问题:

可能是由于Arduino的官方开发板都都比较少有多个i2c、spi接口的情况。遇到过不少库都是用默认的SPI、Wire对象对SPI和I2C接口进行通信,而Arduino也没有提供修改对应对象PIN的API。那么在这里只有通过修改MMA7660库的源代码传入创建指定PIN后的Wire对象才解决了这个问题(当然也可以不用第三方的库,自己写就行,但我这不是懒嘛);

  • MMA7660 初始位置偏移的问题:

因为没接触过姿态传感器的开发,板子明明是平的程序读出来的数据却一直偏向一边,后来才发现是要校准——就是减去在水平时读取到的偏移值。

  • MMA7660数据的抖动问题,AD采样滤波问题:

在开发此项目的过程中我发现通过MMA7660读取到的数据经常会有突变的情况,明明没有动,但是返回的数据却会突然有大幅度的变化。我这里采用的是限幅+平均滤波的方法,原因只是因为最简单,一下就想到了。

其他滤波方法可以参考

附件下载
step-gradienter.zip
团队介绍
周海生
团队成员
Hessian
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号