当前位置:网站首页>【GO记录】从零开始GO语言——用GO语言做一个示波器(二)基于arduino的简易示波器

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

2022-08-03 02:19:00 创客协会的阿蛋°

基于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语言的易用性和规范性,相当于其他语言,更简洁高效一些。

原网站

版权声明
本文为[创客协会的阿蛋°]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_51102592/article/details/126088378