D13 - 「类比×电压×输入」

接下来我们开始建立「类比输入视窗」。

何谓类比讯号

和数位讯号只有 0 与 1 两种状态不同,类比讯号是连续的讯号,实际上自然界的物理量都属於类比讯号,例如:声音、光、电压等等。

更详细的定义与说明可以参考以下连结:
wiki - 类比讯号
wiki - 数位讯号

Uno 上的类比输入指的是「电压」讯号,Uno 可以读取 0 至 5V 的电压并转换为数位讯号回传。

具体实现方式为透过 ADC(Analog to Digital Convert)转换电压讯号,Uno 使用的转换器解析度为 10 位元,所以会将 0 至 5V 的电压转换为 0 至 1023(2 的 10 次方 - 1)的数值呈现。

建立类比输入视窗

window-example.vue 复制一份後改个名字,建立 window-analog-input.vue

src\components\window-analog-input.vue

<template lang="pug">
base-window.window-analog-input(
  :pos='pos',
  headerIconColor='red-3',
  body-class='c-col p-20px pt-20px',
  title='类比输入功能'
)
</template>

<style lang="sass">
.window-analog-input
  width: 300px
  height: 400px
</style>

<script>
import BaseWindow from '@/components/base-window.vue';
import mixinWindow from '@/mixins/mixin-window';

export default {
  name: 'WindowAnalogInput',
  components: {
    'base-window': BaseWindow,
  },
  mixins: [mixinWindow],
  props: {},
  data() {
    return {
      id: this.$vnode.key,
    };
  },
  provide() {
    return {
      id: this.id,
    };
  },
  computed: {},
  watch: {},
  created() {
    console.log(`[ ${this.$options.name} created ] id : `, this.id);
  },
  mounted() {},
  methods: {},
};
</script>

忽然发现其实 data() 中的 idprovide() 内容在每个 window 也都重复出现,所以一样迁移至 mixin-window 中。

src\mixins\mixin-window.js

/**
 * 标准 window 共用内容
 */

export default {
  props: {
    pos: {
      type: Object,
      default() {
        return {
          x: 0,
          y: 0,
        };
      },
    },
  },
  data() {
    return {
      id: this.$vnode.key,
    };
  },
  provide() {
    return {
      id: this.id,
    };
  },
}

并将 window-analog-input.vuewindow-digital-io.vuewindow-example.vue 已迁移的部份删除。

src\components\window-analog-input.vue <script>

import BaseWindow from '@/components/base-window.vue';
import mixinWindow from '@/mixins/mixin-window';

export default {
  name: 'WindowAnalogInput',
  components: {
    'base-window': BaseWindow,
  },
  mixins: [mixinWindow],
  props: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  created() {
    console.log(`[ ${this.$options.name} created ] id : `, this.id);
  },
  mounted() {},
  methods: {},
};

内容变得更清爽了!

接着回到 app.vue,将右键选单内加入『新增「类比输入视窗」』选项,并引入组件。

src\app.vue <template lang="pug">

.screen(@click='handleClick')
  // ...

	// 右键选单
  q-menu(context-menu, content-class='border-radius-s')
    q-list.min-w-260px
      q-item(@click='addWindow("window-digital-io")', clickable, v-close-popup)
        q-item-section
          | 新增「数位 I/O 视窗」
			q-item(@click='addWindow("window-analog-input")', clickable, v-close-popup)
        q-item-section
          | 新增「类比输入视窗」

src\app.vue <script>

// ...

import WindowDigitalIo from '@/components/window-digital-io.vue';
import WindowAnalogInput from '@/components/window-analog-input.vue';

export default {
  name: 'App',
  components: {
    'dialog-system-setting': DialogSystemSetting,
    'window-digital-io': WindowDigitalIo,
		'window-analog-input': WindowAnalogInput,
  },
  // ...
};

加入视窗内容

「选择脚位的下拉选单」已经建立完成,直接引入 base-select-pin.vue

src\components\window-analog-input.vue <script>

import mixinWindow from '@/mixins/mixin-window';

import BaseWindow from '@/components/base-window.vue';
import BaseSelectPin from '@/components/base-select-pin.vue';

export default {
  name: 'WindowAnalogInput',
  components: {
    'base-window': BaseWindow,
    'base-select-pin': BaseSelectPin,
  },
  mixins: [mixinWindow],
  props: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  created() {
    console.log(`[ ${this.$options.name} created ] id : `, this.id);
  },
  mounted() {},
  methods: {},
};

src\components\window-analog-input.vue <template lang="pug">

base-window.window-analog-input(
  :pos='pos',
  headerIconColor='red-3',
  body-class='c-col p-20px pt-20px',
  title='类比输入功能'
)
  base-select-pin(color='red-3')

Untitled

元件复用的感觉真好 ヾ(◍'౪`◍)ノ゙

接着便是提供脚位清单资料作为 base-select-pin.vue 的 options 显示,在 computed 增加 supportPins,提供支援类比功能脚位清单。

src\components\window-analog-input.vue <script>

import { mapState } from 'vuex';

// ...

import { PinMode } from '@/script/utils/firmata.utils';
const { ANALOG_INPUT } = PinMode;

export default {
  name: 'WindowAnalogInput',
  // ...
  computed: {
    ...mapState({
      boardPins: (state) => state.board.info.pins,
    }),

		// 支援功能的脚位
    supportPins() {
      /** @type {PinInfo[]} */
      const boardPins = this.boardPins;

      return boardPins.filter((pin) => {
        const hasMode = pin.capabilities.some(
          (capability) => ANALOG_INPUT === capability.mode
        );

        return hasMode;
      });
    },
  },
  // ...
};

src\components\window-analog-input.vue <template lang="pug">

base-window.window-analog-input(
  :pos='pos',
  headerIconColor='red-3',
  body-class='c-col p-20px pt-20px',
  title='类比输入功能'
)
  base-select-pin(:pins='supportPins', color='red-3')

看看结果如何。

D13 - 类比输入脚位 select options.gif

可以看到只剩下 Pin 14 到 Pin 19。

储存建立脚位

这个部分基本上与「数位 I/O 视窗」相同。

  • 增加 existPins 变数,储存目前已建立脚位
  • 绑定 base-select-pin.vueselected 事件,接收被选择的脚位。

src\components\window-analog-input.vue <script>

/**
 * @typedef {import('@/types/type').PinInfo} PinInfo
 */

// ...

export default {
  name: 'WindowAnalogInput',
  // ...
  data() {
    return {
      /** @type {PinInfo[]} */
      existPins: [],
    };
  },
  // ...
  methods: {
		/** 新增脚位
     * @param {PinInfo} pin
     */
    addPin(pin) {
      if (!pin) return;

      this.$store.commit('window/addOccupiedPin', {
        id: this.id,
        pin,
      });

      this.existPins.push(pin);
    },
		/** 移除脚位
     * @param {PinInfo} pin
     */
    deletePin(pin) {
      if (!pin) return;

      this.$store.commit('window/deleteOccupiedPin', {
        id: this.id,
        pin,
      });

      const index = this.existPins.findIndex(
        (existPin) => existPin.number === pin.number
      );
      this.existPins.splice(index, 1);
    },

    /** 接收错误讯息 */
    handleErr(msg) {
      this.$q.notify({
        type: 'negative',
        message: msg,
      });
    },
  },
};

src\components\window-analog-input.vue <template lang="pug">

base-window.window-analog-input(
  :pos='pos',
  headerIconColor='red-3',
  body-class='c-col p-20px pt-20px',
  title='类比输入功能'
)
  base-select-pin(
    :pins='supportPins',
    color='red-3',
    @selected='addPin',
    @err='handleErr'
  )

试试看效果如何。

D13 - 类比输入视窗选择脚位.gif

太棒了!再来就是建立类比输入控制组件,显示类比输入数值。

总结

  • 成功建立类比输入视窗。
  • 引入 base-select-pin 组件,用於选择脚位。
  • 储存选择脚位清单。

以上程序码已同步至 GitLab,大家可以前往下载:

GitLab - D13


<<:  【没钱买ps,PyQt自己写】Day 12 - 建立一个可以缩放图片大小的显示器 (基於 QImage 使用 OpenCV)

>>:  Day 15 - 从Business Intelligence(BI)到AI

敏捷方法或框架-极限编程(XP)提供了最多的程序开发实务

敏捷是一种心态,秉承《敏捷软件开发和实践宣言》中所述的四个价值观和十二个原则。敏捷是一个笼统的术语。...

第三十天:为 TeamCity 设计的 Kotlin DSL

一直以来,我们使用 TeamCity 时都是透过 Web UI 来设定,不论 Project 的 V...

自动化测试,让你上班拥有一杯咖啡的时间 | Day 10 - 如何产生测试报告

此系列文章会同步发文到个人部落格,有兴趣的读者可以前往观看喔。 执行完测试脚本後,不仅会有截图和影...

Thunkable学习笔记 9 - 资产盘点(二)

对thunkable的data sources还不是很清楚, 建立这个app练习并测试这个物件的特性...

表单攻略前准备

这需要一个完整的例子。 我先依照先前讲的把程序码先准备好 先看画面 准备了两个页面: User, U...