Bash 简单正弦波发生器的脚本数组算法问题
Problem with Bash Script array arithmetic for simple sine wave generator
我对 bash 脚本和 linux 总体上还很陌生。我正在尝试向压力调节器发送一系列快速命令(相隔半秒),我通常使用 bash 脚本通过简单的方形脉冲来发送这些命令。但是,我似乎无法为正弦波形脉冲获得正确的语法。我找不到使用实际正弦函数的方法,但一系列小的离散步骤也可以。
这是我的脚本:
#!/bin/bash
Pmax="90"
Pmin="10"
Rcor="7.91" #This converts the pressure setting into the devices scaled range.
declare -a Sinewave20=(0 0.309 0.588 0.809 0.951 1 0.951 0.809 0.580 0.309 0 -0.309 -0.588 -0.809 -0.951 -1 -0.951 -0.809 -0.588 -0.309)
Amplitude=$(( $Pmax-$Pmin ))
Offset=$(( $Pmin+$Amplitude/2 ))
# 6 cycles of Sinewave20 corresponds to 1 min of .1 hz sine wave
for i in {0..6}
do
# Let's send the commands for a 20 pt sine wave
for x in "${!Sinewave20[@]}";
do
Value=$(( $Amplitude*$Rcor*$Sinewave20[x]+{Offset*$Rcor ))
echo -e "SET ${Value}\r" > /dev/ttyUSB1
sleep 0.5
done
done
这会导致以下错误消息:
第 18 行:80*7.91*0[x]+{Offset*7.91:语法错误:无效算术运算符(错误标记为“.91*0[x]+{Offset*7.91”)
我尝试了多种写法,但没有找到一种可行的方法。改变压力的命令很简单:
echo -e "SET 100\r" > /dev/ttyUSB1
Bash 算术仅限于整数。
考虑使用内置支持浮点数的脚本引擎。轻量级 awk
或 bc
,或 full
语言之一:Python、Perl 等
参见:How do I use floating-point division in bash? and https://unix.stackexchange.com/questions/40786/how-to-do-integer-float-calculations-in-bash-or-other-languages-frameworks/40787#40787
你会尝试用 awk
替换:
Pmax="90"
Pmin="10"
Rcor="7.91"
awk -v Pmax="$Pmax" -v Pmin="$Pmin" -v Rcor="$Rcor" '
BEGIN {
PI = atan2(0, -1)
Amplitude = Pmax - Pmin
Offset = Pmin + Amplitude / 2
for (i = 0; i <= 6; i++) {
for (j = 0; j < 20; j++) {
Value = (Amplitude * sin(j / 10 * PI) + Offset) * Rcor
printf("SET %f\r\n", Value) > /dev/ttyUSB1
system("sleep 0.5")
}
}
}'
希望对您有所帮助。
这是 tshiono awk 脚本的修改版本,解决了一些拼写错误(必须引用 /dev/...
,...),技术问题(每次迭代都必须关闭设备,...),以及稍微简化了。
测试脚本:bash script.sh
,它将显示将要发送的值(无延迟)
到运行脚本:bash script.sh /dev/ttyUSB1
。
文件:script.sh
#! /bin/bash
awk -v Device="" '
BEGIN {
Pmax=90
Pmin=10
Rcor=7.91
PI = atan2(0, -1)
Amplitude = Pmax - Pmin
Offset = Pmin + Amplitude / 2
for (i = 0; i <= 6; i++) {
for (j = 0; j < 20; j++) {
Value = (Amplitude * sin(j / 10 * PI) + Offset) * Rcor
printf "Sending: SET %f\r\n", Value > "/dev/stderr"
if ( Device ) {
printf "SET %f\r\n", Value > Device
close(Device)
system("sleep 0.5")
}
}
}
}'
我对 bash 脚本和 linux 总体上还很陌生。我正在尝试向压力调节器发送一系列快速命令(相隔半秒),我通常使用 bash 脚本通过简单的方形脉冲来发送这些命令。但是,我似乎无法为正弦波形脉冲获得正确的语法。我找不到使用实际正弦函数的方法,但一系列小的离散步骤也可以。
这是我的脚本:
#!/bin/bash
Pmax="90"
Pmin="10"
Rcor="7.91" #This converts the pressure setting into the devices scaled range.
declare -a Sinewave20=(0 0.309 0.588 0.809 0.951 1 0.951 0.809 0.580 0.309 0 -0.309 -0.588 -0.809 -0.951 -1 -0.951 -0.809 -0.588 -0.309)
Amplitude=$(( $Pmax-$Pmin ))
Offset=$(( $Pmin+$Amplitude/2 ))
# 6 cycles of Sinewave20 corresponds to 1 min of .1 hz sine wave
for i in {0..6}
do
# Let's send the commands for a 20 pt sine wave
for x in "${!Sinewave20[@]}";
do
Value=$(( $Amplitude*$Rcor*$Sinewave20[x]+{Offset*$Rcor ))
echo -e "SET ${Value}\r" > /dev/ttyUSB1
sleep 0.5
done
done
这会导致以下错误消息:
第 18 行:80*7.91*0[x]+{Offset*7.91:语法错误:无效算术运算符(错误标记为“.91*0[x]+{Offset*7.91”)
我尝试了多种写法,但没有找到一种可行的方法。改变压力的命令很简单:
echo -e "SET 100\r" > /dev/ttyUSB1
Bash 算术仅限于整数。
考虑使用内置支持浮点数的脚本引擎。轻量级 awk
或 bc
,或 full
语言之一:Python、Perl 等
参见:How do I use floating-point division in bash? and https://unix.stackexchange.com/questions/40786/how-to-do-integer-float-calculations-in-bash-or-other-languages-frameworks/40787#40787
你会尝试用 awk
替换:
Pmax="90"
Pmin="10"
Rcor="7.91"
awk -v Pmax="$Pmax" -v Pmin="$Pmin" -v Rcor="$Rcor" '
BEGIN {
PI = atan2(0, -1)
Amplitude = Pmax - Pmin
Offset = Pmin + Amplitude / 2
for (i = 0; i <= 6; i++) {
for (j = 0; j < 20; j++) {
Value = (Amplitude * sin(j / 10 * PI) + Offset) * Rcor
printf("SET %f\r\n", Value) > /dev/ttyUSB1
system("sleep 0.5")
}
}
}'
希望对您有所帮助。
这是 tshiono awk 脚本的修改版本,解决了一些拼写错误(必须引用 /dev/...
,...),技术问题(每次迭代都必须关闭设备,...),以及稍微简化了。
测试脚本:bash script.sh
,它将显示将要发送的值(无延迟)
到运行脚本:bash script.sh /dev/ttyUSB1
。
文件:script.sh
#! /bin/bash
awk -v Device="" '
BEGIN {
Pmax=90
Pmin=10
Rcor=7.91
PI = atan2(0, -1)
Amplitude = Pmax - Pmin
Offset = Pmin + Amplitude / 2
for (i = 0; i <= 6; i++) {
for (j = 0; j < 20; j++) {
Value = (Amplitude * sin(j / 10 * PI) + Offset) * Rcor
printf "Sending: SET %f\r\n", Value > "/dev/stderr"
if ( Device ) {
printf "SET %f\r\n", Value > Device
close(Device)
system("sleep 0.5")
}
}
}
}'