LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

开箱测试合宙 Air001

参考

开发环境

  • Linux Container Nspawn
  • VSCode + Arduino Extension
  • Air001 Board
  • CH340
  • HC-HR04 + RGB LED

动手

这块 Air001 板子的 USB 只是通电作用,要与之沟通是需要合宙的 Dlink 或者用传统的 UART,为了大多数板子能能统一,最好还是外接个 CHxxx/PLxxx 来通信。

合宙的板子基本都是要自己焊排针的,可是有个非常神奇的地方就是,按键和 LED 居然和 IO 定义是在不同面的,这就很不友好,你经常得翻来翻去,我想连在面包板上就显得不妥了,所以也没有买来焊,直接用杜邦碰瓷 GND TX RX 5V 四个触点来烧录,缺点吗,就是手不能抖,经常烧录十次才能成功一次,所以程序尽量就控制一次能搞定不用调试是最好的。

为了不污染系统,我们最好把开发环境都弄到系统级别的容器里,如 LXC 或者 Nspawn,然后 VSCode Remote 开发,这时候容器就得能控制到设备:

machinectl shell -q development /bin/bash -c "mknod -m 666 /dev/ttyUSB0 c 188 0"

VSCode 连上 development 容器后,装上 Arduino 扩展就可以,然后 Ctrl+Shift+P 打开 Boards Manager,点击 Additional Urls 或这直接在 VSCode Setings 里,给 arduino.additionalUrls 加上下列地址:

刷新后,搜索 Air MCU 进行下载。

之后就是 Arduino 的开发流程,Board Configuration 里头选择 Air001 Dev,VSCode 在这时候,可能会提示 Arduino 的一些基础函数,如 pinMode 等找不到,参考 Github,在 VSCode 项目配置文件 .vscode/settings.json 加入 "C_Cpp.intelliSenseEngine": "Tag Parser",但是这样也会让 C++ 从只能补全变为模糊补全,而实际测试,发现是合宙 Air001 代码的问题,对 c++17 支持不好却将其设置默认,所以我们依旧保留 "C_Cpp.intelliSenseEngine": "default",然后在对应 Air001 的库文件夹加入编译选项:

cd ~/.arduino15/packages/AirM2M/hardware/AirMCU/0.4.0
echo 'compiler.c.std=gnu11' >> platform.local.txt
echo 'compiler.cpp.std=gnu++11' >> platform.local.txt

这时候我们可以写一段简单的 demo 来测试,LED 根据距离由近到远从红变到紫:

#define AIR_GREEN_PORT PB_0
#define AIR_RED_PORT PB_1
#define AIR_BLUE_PORT PB_3

#define RED_PORT PA_0
#define GREEN_PORT PA_1
#define BLUE_PORT PA_7

#define TRIG_PORT PF_1
#define ECHO_PORT PF_0

# 最大亮度值
static int MAX_VALUE = 240;
# 每种颜色亮度变到下种颜色的槛数,每个槛对应 1cm 距离
static int UNIT = 6;

static int STEP = MAX_VALUE / UNIT;
static int LEVEL[6] = {2, -1, 3, -2, 1, -3};

void turn_air_light() {
    digitalWrite(AIR_GREEN_PORT, HIGH);
    digitalWrite(AIR_RED_PORT, HIGH);
    digitalWrite(AIR_BLUE_PORT, HIGH);
}

double calc_distance() {
  digitalWrite(TRIG_PORT, LOW);
  delayMicroseconds(2);

  digitalWrite(TRIG_PORT, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PORT, LOW);

  return pulseIn(ECHO_PORT, HIGH) * 0.034 / 2;
}

void make_light_colorful(double distance) {
  if (distance >= UNIT * 6) {
    distance = UNIT * 6.0 - 1;
  }

  int colors[3] = {0, 0, 0};
  
  int level_value = LEVEL[(int)(distance) / UNIT];
  int unit_value = (int)(distance) % UNIT;
  int index = level_value - 1;
  int value = unit_value * STEP;
  int max_value_index = (index - 1 + 3) % 3;

  if (level_value < 0) {
    value = MAX_VALUE - unit_value * STEP;
    index = level_value * -1 - 1;
    max_value_index = (index + 1) % 3;
  }

  colors[max_value_index] = MAX_VALUE;
  colors[index] = value;

  analogWrite(RED_PORT, colors[0]);
  analogWrite(GREEN_PORT, colors[1]);
  analogWrite(BLUE_PORT, colors[2]);
  
  Serial.printf("(%d %d %d) %d\n", colors[0], colors[1], colors[2], (int)distance);
}

void setup() {
  pinMode(AIR_GREEN_PORT, OUTPUT);
  pinMode(AIR_RED_PORT, OUTPUT);
  pinMode(AIR_BLUE_PORT, OUTPUT);

  pinMode(TRIG_PORT, OUTPUT);
  pinMode(ECHO_PORT, INPUT);

  digitalWrite(AIR_GREEN_PORT, LOW);
  digitalWrite(AIR_RED_PORT, LOW);
  digitalWrite(AIR_BLUE_PORT, LOW);

  analogWrite(RED_PORT, 0);
  analogWrite(GREEN_PORT, 0);
  analogWrite(BLUE_PORT, 0);

  turn_air_light();

  Serial.begin(115200);
}

void loop() {
  double distance = calc_distance();

  make_light_colorful(distance);

  delay(500);
}

按住板子上的 Boot 键,然后短按 RST 键,释放 Boot 键就会进入刷机模式,要注意连线,这里灯用的是 PA0 PA1 PA7,因为很多 PA 都被占用了,让你没有焊接还要换几次 IO 口来烧录,真要了老命。样例显示效果如下: