Go实现树莓派超声波测距

后面发现调用的两个Go的库进行测算还是没办法读到好的超声波值, 所以放弃

公式

距离(cm)=((声速(m/s)×时间(ms))/ 2) *10

代码

ultrasonicSensor.go

package main

import (
	"context"
	"errors"
	"fmt"
	"periph.io/x/conn/v3/gpio"
	"periph.io/x/conn/v3/gpio/gpioreg"
	"time"
)

var (
	TimeoutError = errors.New("timeout error")
)

const (
	SpeedOfSound = 34300.0 // cm/s
)

type UltrasonicSensor struct {
	triggerIO gpio.PinIO
	echoIO    gpio.PinIO

	started  bool
	canceled chan struct{}
}

func NewUltrasonicSensor(triggerPinName, echoPinName string) (*UltrasonicSensor, error) {
	var (
		us = &UltrasonicSensor{
			canceled: make(chan struct{}),
		}
		err error
	)
	us.triggerIO = gpioreg.ByName(triggerPinName)
	if nil == us.triggerIO {
		return nil, errors.New("can't find trigger pin")
	}
	us.echoIO = gpioreg.ByName(echoPinName)
	if nil == us.echoIO {
		return nil, errors.New("can't find echo pin")
	}
	return us, err
}

func (u *UltrasonicSensor) Init() error {
	err := u.triggerIO.Out(gpio.Low)
	if nil != err {
		return err
	}
	err = u.echoIO.In(gpio.PullDown, gpio.NoEdge)
	return nil
}

func (u *UltrasonicSensor) Destroy() error {
	return nil
}

func (u *UltrasonicSensor) Start(detectInterval time.Duration, onDistanceChanged func(cm float64, err error) error) error {
	go u.run(detectInterval, onDistanceChanged)
	return nil
}

func (u *UltrasonicSensor) run(detectInterval time.Duration, onDistanceChanged func(cm float64, err error) error) {
	if u.started {
		return
	}
	u.started = true
	defer func() {
		select {
		case <-u.canceled:
		default:
		}
		u.started = false
	}()

	var (
		err          error
		distance     float64
		distanceTemp float64
		/*
			声速大约是343米/秒, 超声波模块最大测量是2m ~ 6m
			时间(s) = 2*距离(m)/声速(m/s) = 2 * 6 / 343 ≈ 0.035
		*/
		maxWaitTime = time.Millisecond * 35 //35
		parentCtx   = context.Background()
		ctx         context.Context
	)
	for {
		err = u.ultrasonicPulseOut() // 发送超声波
		if nil != err {
			onDistanceChanged(0, err)
			return
		}
		ctx, _ = context.WithTimeout(parentCtx, maxWaitTime)
		distanceTemp, err = u.getDist(ctx)
		if nil != err {
			if TimeoutError != err {
				onDistanceChanged(0, err)
				return
			}
			fmt.Println("read timeout")
			time.Sleep(detectInterval)
			continue
		}

		if distance != distanceTemp {
			distance = distanceTemp
			if err = onDistanceChanged(distance, nil); nil != err {
				return
			}
		}

		time.Sleep(detectInterval)
	}
}

func (u *UltrasonicSensor) ultrasonicPulseOut() (err error) {
	if err = u.triggerIO.Out(gpio.High); nil != err {
		return err
	}
	time.Sleep(time.Microsecond * 10) // 10us
	if err = u.triggerIO.Out(gpio.Low); nil != err {
		return err
	}
	time.Sleep(time.Microsecond * 1)
	return
}

func (u *UltrasonicSensor) getDist(ctx context.Context) (float64, error) {
	var (
		startDateTime time.Time // 开启超声波计时
	)

	waitForNext := func() error {
		select {
		case <-ctx.Done():
			return TimeoutError
		case <-u.canceled:
			return errors.New("cancel error")
		case <-time.After(time.Nanosecond * 1): // 读取引脚延时,也是软件最大误差
		}
		return nil
	}

	/* wait for start */
	for gpio.Low == u.echoIO.Read() {
		if err := waitForNext(); nil != err {
			return 0, err
		}
	}
	startDateTime = time.Now()

	/* wait for end */
	for gpio.High == u.echoIO.Read() {
		if err := waitForNext(); nil != err {
			return 0, err
		}
	}
	return time.Since(startDateTime).Seconds() * SpeedOfSound / 2.0, nil
}

func (u *UltrasonicSensor) Stop() error {
	if !u.started {
		return nil
	}
	select {
	case u.canceled <- struct{}{}:
	case <-time.After(time.Second * 2):
		return errors.New("cancel timeout")
	}
	return nil
}

main.go

package main

import (
	"fmt"
	"log"
	"periph.io/x/host/v3"
	"sync"
	"time"
)

func main() {
	var (
		waiter sync.WaitGroup
	)

	// 初始化硬件
	if _, err := host.Init(); err != nil {
		log.Fatal(err)
	}
	sensor, err := NewUltrasonicSensor("GPIO17", "GPIO27")
	if nil != err {
		fmt.Println(err)
		return
	}
	if err = sensor.Init(); nil != err {
		fmt.Println("sensor init fail, ", err.Error())
		return
	}
	defer sensor.Destroy()
	waiter.Add(1)
	sensor.Start(time.Second, func(cm float64, err error) error {
		if nil != err {
			waiter.Done()
			fmt.Println(err)
			return err
		}

		fmt.Println("Distance ", cm, "(cm)")

		return nil
	})
	waiter.Wait()
}

Note

注意电源一定要选对, 否则输出功率不够无法准确测量距离…

参考

树莓派|超声波传感器

GPIO-ZERO DistanceSensor

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/601350.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯13届JAVA A组 国赛

​​​​​​​ package 蓝桥杯国赛; // 贪心选个数最少的进行摆 // 2:1 ,3:1, 4:1,5 : 3,6:3,7:1 // 选 1&#xff0c;7&#xff0c;4&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;9 // 然后都选满10个 public class 火彩棒数字 {public static void main(String[] a…

超越传统游戏:生成式人工智能对游戏的变革性影响

人工智能&#xff08;AI&#xff09;在游戏中的应用 游戏产业是一个充满活力、不断发展的领域&#xff0c;人工智能&#xff08;AI&#xff09;的融入对其产生了重大影响。这一技术进步彻底改变了游戏的开发、玩法和体验方式。本文分析的重点是传统人工智能和生成式人工智能在游…

Go微服务精讲:Go-Zero全流程实战即时通讯(超清)

go-zero 是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性&#xff0c;经受了充分的实战检验。 Go微服务精讲&#xff1a;Go-Zero全流程实战即时通讯(超清) go-zero 中的 api&#xff0c;rpc&#xff0c;数据库等涉及的代码&#xff0c;…

专题模块项目功能说明和运行方法-02

项目集介绍 SpringbootSeries父工程 此模块中只有一个pom.xml文件&#xff0c;是后面所有模块的父模块&#xff0c;主要功能有两个&#xff1a;子模块管理和依赖管理。 类别必选可选基础框架jdk 17 spring-boot-starter 3.2.4spring-boot-starter-web 3.2.4spring-cloud 2023…

适合小白使用的编译器(c语言和Java编译器专属篇)

本节课主要讲如何安装适合编程小白的编译器 废话不多说&#xff0c;我们现在开始 c/c篇 首先&#xff0c;进入edge浏览器&#xff0c;在搜索框输入visual studio &#xff0c;找到带我画圈的图标&#xff0c;点击downloads 找到community版&#xff08;社区版&#xff09;的下…

C#核心之面向对象相关知识点

面向对象相关知识点 文章目录 1、命名空间1、命名空间基本概念2、命名空间的使用3、不同命名空间中相互调用4、不同命名空间中允许有同类名5、命名空间可以包裹命名空间6、关于修饰类的访问修饰符 2、万物之父中的方法1、object中的静态方法2、object中的成员方法3、object中的…

Unity 性能优化之UI和模型优化(九)

提示&#xff1a;仅供参考&#xff0c;有误之处&#xff0c;麻烦大佬指出&#xff0c;不胜感激&#xff01; 文章目录 前言一、选择UI二、UGUI的优化1.Raycast Target2.UI控件的重叠3.TextMeshPro 二、模型优化1.Model选项卡Mesh CompressionRead/Write Enabled设置Optimize Ga…

IIoT:数据融合在工业物联网中的应用——青创智通

工业物联网解决方案-工业IOT-青创智通 随着科技的不断发展&#xff0c;工业物联网&#xff08;IIoT&#xff09;已经逐渐渗透到各个行业&#xff0c;为企业的生产和管理带来了前所未有的便利。 然而&#xff0c;与此同时&#xff0c;海量的数据也为企业带来了挑战。如何将这些…

图片8位, 16位,24位,32位原理,以及如何进行补位互转

写在前面&#xff1a;之前一直没有这个概念&#xff0c;以为像素就是十六进制如 #FFFFFF&#xff0c;或者rgb(255,255,255) 即可实现颜色定义&#xff0c;理解相当肤浅&#xff0c;接触到一个物联网项目&#xff0c;写底层的童鞋让我把16位如 0*FFFF转为24位去显示在浏览器&…

如何使用SkyWalking收集分析分布式系统的追踪数据

Apache SkyWalking 是一个开源的观测性工具&#xff0c;用于收集、分析和展示分布式系统的追踪数据。SkyWalking 支持多种语言的追踪&#xff0c;包括但不限于 Java、.NET、Node.js 等。以下是使用 SkyWalking 工具实现数据采集的详细步骤&#xff1a; 1. 下载和安装 SkyWalkin…

MCU做死循环时,到底应该用for(;;) 还是wihile(1)

MCU做死循环时 for while stm32中老工程师用forfor while背景for版本while版本正方观点&#xff1a;哪有好的编译器&#xff1a;反方观点&#xff1a;这种代码过时了工程师实地测试&#xff1a;和编译器和优化有关 建议还是用for参考 stm32中老工程师用for /* Start scheduler …

MS2107 宏晶微 音视频采集芯片 提供开发资料

1. 基本介绍 MS2107 是一款视频和音频采集芯片,内部集成 USB2.0 控制器和数据收发模块、视频 ADC模块、音频 ADC 模块和音视频处理模块。MS2107可以将 CVBS、S-Video 和音频信号通过 USB接口传送到 PC、智能手机和平板电脑上预览或采集。MS2107 输出支持 YUV422 和 MJPEG 两种…

css: hover 划过显示/隐藏 div 样式

1. 图例: 划过用display: block;和 display: none; 显示div和隐藏div div: <div class="sectorBox"> <div v-for="(item, index) in sectorList" :key="index" class="sill"> <div class="si…

三维点云处理-聚类(下)

接着前一部分数据聚类方法的介绍&#xff0c;由于K-means和GMM方法都是基于欧式距离信息处理的&#xff0c;两者分别以圆形和椭圆形来作为数据的聚类分割方式&#xff0c;这种情况下会导致环形图和月牙图数据分割不准确&#xff0c;因此进一步的介绍一种谱聚类方法&#xff0c;…

Elastic 通过 AI 驱动的安全分析改变 SIEM 游戏

作者&#xff1a;Santosh Krishnan, Jennifer Ellard 借助由搜索 AI 提供支持的新攻击发现功能&#xff0c;优先考虑攻击&#xff0c;而不是警报。 传统的安全信息与事件管理系统&#xff08;SIEM&#xff09;在很大程度上依赖屏幕背后的人类才能取得成功。警报、仪表盘、威胁…

Python高级编程-DJango2

Python高级编程-DJango2 没有清醒的头脑&#xff0c;再快的脚步也会走歪&#xff1b;没有谨慎的步伐&#xff0c;再平的道路也会跌倒。 目录 Python高级编程-DJango2 1.显示基本网页 2.输入框的形式&#xff1a; 1&#xff09;文本输入框 2&#xff09;单选框 3&#xff…

我用 GitHub 9.8k 的 Go 语言 2D 游戏引擎写了个游戏

前言 hi&#xff0c;大家好&#xff0c;这里是白泽。今天给大家分享一个 GitHub &#x1f31f;9.8k 的 Go 语言 2D 游戏引擎。 https://github.com/hajimehoshi/ebiten 引擎的贡献者依旧在积极维护&#xff0c;是一个兼具学习 & 娱乐的项目&#xff01; 为此我也用这个…

数据结构-线性表-应用题-2.2-11

1)算法的基本设计思想&#xff1a; 分别求两个升序序列的中位数a,b 若ab&#xff0c;则a或b即为所求中位数 若a<b&#xff0c;则舍弃A中较小的一半&#xff08;中位数偏小&#xff0c;往后面找&#xff09;&#xff0c;同时舍弃序列B中较大的一半&#xff0c;两次舍弃长度…

meshlab: pymeshlab保存物体的横截面(compute planar section)

一、关于环境 请参考&#xff1a;pymeshlab遍历文件夹中模型、缩放并导出指定格式-CSDN博客 二、关于代码 本文所给出代码仅为参考&#xff0c;禁止转载和引用&#xff0c;仅供个人学习。 # pymeshlab需要导入&#xff0c;其一般被命名为ml import pymeshlab as ml# 本案例所…

C++ | Leetcode C++题解之第74题搜索二维矩阵

题目&#xff1a; 题解&#xff1a; class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int m matrix.size(), n matrix[0].size();int low 0, high m * n - 1;while (low < high) {int mid (high - low) / 2 l…