【GO记录】从零开始GO语言——用GO语言做一个示波器(二)基于arduino的简易示波器

基于arduino的简易示波器

演示视频

用TinyGO语言做一个基于arduino的简易示波器

原理

原理就是用arduino获取高低电平模拟值的跳变,这就是示波器的电压值了,然后再来判断跳变的时间,来达到获取PWM或者触发信号的效果。

理论上应该用定时器加外部中断会比较号一点,但是我在TinGo中没找到定时器计时和外部中断的代码,所以就没做出来,然后arduino的时钟频率实在太低了,才16M。

示例代码地址:https://tinygo.org/docs/reference/microcontrollers/machine/bluepill/

思路

/*
*思路:PWM波形是这样的:
*__    __    __
*  |__|  |__|
*我只需要捕获上升沿以及下降沿、周期的时间就可以计算出他的频率了
*电压使用ADC中获取的数值就可以了
 */

代码

package main

import (
	"machine" //支持包
	"time"    //时间函数
)

//变量
var (
	//串口变量
	uart   = machine.Serial
	tx     = machine.UART_TX_PIN
	rx     = machine.UART_RX_PIN
	sensor machine.ADC

	//自定义变量
	//时间变量
	OS_time       uint64
	last_time     uint64
	now_time      uint64
	sys_time      time.Time
	delay1s       uint64 = 1000000000
	led_test_time uint64 = 0

	Pwm_time [10]uint64
	Pwm_Down uint64
	Pwm_Rise uint64

	//电压变量
	Vol_times     int
	voltage       uint16 = 0
	Vol_arr       [5]uint16
	Vol_default   uint16
	Vol_Down      uint16
	Vol_Rise      uint16
	Last_Vol_Rise uint16
)

//调试代码
func My_time() {
	sys_time := time.Now()
	now_time = sys_time.Nsec1()      //现在的计数周期  速度是16M	实际上测试并不准确
	OS_time = (now_time - last_time) //单位:10ns	精度在百微秒级
	last_time = now_time

	//	println(now_time)
	//println(sys_time.Nanosecond())
	//println(OS_time) //系统运行周期所占时间
}

func led_test(led machine.Pin) {

	led_time := (now_time - led_test_time)
	if led_time > delay1s*2 {
		led.High()
		led_test_time = now_time
		//print("\r\nledtime:")
		//print(led_test_time)

		print("\r\n")
		/*		for i := 0; i <= Vol_times; i++ {
				print("\r\n")
				print(i)
				print(":")
				print(Vol_arr[i])
			}*/
		print("\r\n")

	} else {
		//	println(now_time - led_test_time)
		//		println(led_test_time)
		led.Low()
	}

}

func main() {

	//led引脚初始化 PD13
	led := machine.LED
	led.Configure(machine.PinConfig{Mode: machine.PinOutput})

	//串口1波特率:9600
	uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
	uart.Write([]byte("UART_init BaudRate:9600\r\n"))

	//ADC初始化
	machine.InitADC()
	sensor = machine.ADC{machine.ADC0}
	sensor.Configure(machine.ADCConfig{}) //配置 参考电压、转换bit、单次采样次数		16bit:(0--5V)min=0	x=65535
	voltage := sensor.Get()               //获取电压值
	uart.Write([]byte("\r\nvol:"))        //打印电压
	print(voltage)

	sys_time := time.Now()       //获取时间值
	last_time = sys_time.Nsec1() //获取纳秒
	led_test_time = last_time
	uart.Write([]byte("\r\nsys_time:")) //打印时间
	print(last_time)

	for {
		//获取系统时间
		My_time()

		//获取ADC
		//AD_Sample() //电压采样调试
		AD_Pwm_Sample(sensor) //PWM捕获

		//led_test(led)
	}
}

func AD_Sample() {

	voltage := sensor.Get()
	//str1 := strconv.Itoa(int(voltage)) //整转串  方便打印
	//println("adc0:" + str1)
	voltage1 := uint32(voltage)
	voltage1 = ((voltage1 * 1000) / 65472) * 5 //此公式为 ((ADC的模拟值电压*精度)/转换bit)*参考电压  bit原理上应该为65535 但是实测5V时只有65472
	voltage = uint16(voltage1 / 1)
	//str1 = strconv.Itoa(int(voltage)) //整转串  方便打印
	//println("vol:" + str1)
	println(voltage)
	Vol_arr[Vol_times] = voltage
	println(Vol_arr[Vol_times])

	if Vol_times >= 99 {
		Vol_times = 0
	} else {
		Vol_times++
	}

	//uart.Write([]byte("\r\nvol:"))
	//print(voltage)

}

func AD_Sample2() (v uint16) {

	voltage := sensor.Get()
	voltage1 := uint32(voltage)
	voltage1 = ((voltage1 * 1000) / 65472) * 5 //此公式为 ((ADC的模拟值电压*精度)/转换bit)*参考电压  bit原理上应该为65535 但是实测5V时只有65472
	voltage = uint16(voltage1 / 1)             //可取精度1~1000  1000时单位为V
	//println(voltage)
	return voltage
}

/*
*思路:PWM波形是这样的:
*__    __    __
*  |__|  |__|
*我只需要捕获上升沿以及下降沿、周期的时间就可以计算出他的频率了
*电压使用ADC中获取的数值就可以了
 */
func AD_Pwm_Sample(sen machine.ADC) {
	i := 0

	for {
		voltage = AD_Sample2()
		//print("\r\nVol:")
		//print(voltage)
		//第一次上升沿
		if voltage > 4990 { //如果电压大于5000mV  默认触发电平为5000
			sys_time = time.Now()
			Pwm_time[0] = sys_time.Nsec1() //记录现在的时间
			Vol_arr[0] = voltage           //记录现在的电压值
			//记录PWM中第一次下降沿时间
			for {
				voltage = AD_Sample2() //获取电压
				if voltage < 130 {     //如果电压小于30mv(防止BUG,本应该是0v)
					sys_time = time.Now()
					Pwm_time[1] = sys_time.Nsec1() //记录现在的时间
					Vol_arr[1] = voltage           //记录现在的电压值
					break                          // 退出for循环
				}
			}
			//记录PWM中第二次上升沿的时间
			for {
				voltage = AD_Sample2() //获取电压
				if voltage > 4990 {    //如果电压大于3000mV
					sys_time = time.Now()
					Pwm_time[2] = sys_time.Nsec1() //记录现在的时间
					Vol_arr[2] = voltage           //记录现在的电压值
					i = 1
					break // 退出for循环
				}
			}
		}

		if i == 1 {

			Vol_default = Vol_arr[0]
			Vol_Down = Vol_arr[1]
			Vol_Rise = Vol_arr[2]
			Pwm_Down = (Pwm_time[1] - Pwm_time[0]) / 1000000 //下降沿时间 单位是ms
			Pwm_Rise = (Pwm_time[2] - Pwm_time[0]) / 1000000 //上升沿时间 单位是ms

			//软件debug
			Pwm_time[3] = Pwm_Rise
			Pwm_time[4] = Pwm_time[3]
			Pwm_time[5] = Pwm_time[4]
			Pwm_time[6] = Pwm_time[5]
			Pwm_time[7] = Pwm_time[6]

			if Pwm_time[3] == Pwm_time[4] {
				if Pwm_time[4] == Pwm_time[5] {
					if Pwm_time[5] == Pwm_time[6] {
						if Pwm_time[6] == Pwm_time[7] {
							//Last_Vol_Rise = Vol_Rise
							print_debug()
							break
						}
					}
				}
			}

			/*
				if Vol_Rise != Last_Vol_Rise {
					flag++
					if flag >= 50 { //如果检测的脉冲总时长变化 需要检测50次才可确认 以此滤波 防止干扰信号
						flag = 0
						Last_Vol_Rise = Vol_Rise
					}
				} else if Vol_Rise == Last_Vol_Rise {
					//Last_Vol_Rise = Vol_Rise
					flag = 0
					print_debug()
					break
				}*/

		}
	}

}

func print_debug() {

	print("\rVol:")
	print(voltage)
	print("  Pwm_Down:")
	print(Pwm_Down)
	print("  Pwm_Rise:")
	print(Pwm_Rise)
	print("  Pwm:")
	print(Pwm_Down * 100 / Pwm_Rise)
	print("      ")

}

其实本质上和C++开发没什么区别,只不过GO语言的易用性和规范性,相当于其他语言,更简洁高效一些。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

创客阿蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值